Сравнение Java-Стека

мне интересно, как это сделать:

  1. сравнить два объекта стека
  2. сделать это рекурсивно
  3. после метода, это завершено, стопки остаются такими, какими они были вначале (т. е. тот же порядок, те же предметы).

только push, pop и isEmpty методы Stack доступно.

Я больше ищу теоретическую помощь, чем помощь в кодировании, но любое понимание будет оценено.

3 ответов


в псевдо-коде вы можете сделать что-то вроде этого:

boolean compareStacks(a, b) {
  if (a.isEmpty() != b.isEmpty()) return false; // check if one is empty
  if (a.isEmpty() && b.isEmpty()) return true; // check if both are empty
  element_a = a.pop(); // grab elements and compare them
  element_b = b.pop();
  if (((element_a==null) && (element_b!=null)) || !element_a.equals(element_b)) {
    a.push(element_a); // if they are not equal, restore them and return false
    b.push(element_b);
    return false;
  }
  result = compareStacks(a, b); // compare shortened stacks recursively
  a.push(element_a); // restore elements
  b.push(element_b);
  return result; // return result from recursive call
}

два стека идентичны, если их элементы верхнего уровня идентичны, а остальные стеки идентичны (а именно рекурсивное условие).

теперь подумайте, что делать непосредственно перед возвращением из вызова метода, чтобы оставить стеки так же, как они были заданы во время вызова.

---редактировать---

рабочий код Java (производный от Маркус А. решение, но с интересным использованием "наконец" и с дженерики):

static <T> boolean compareStacks(Stack<T> a, Stack<T> b) {
    if (a.isEmpty() != b.isEmpty()) return false; 
    if (a.isEmpty() && b.isEmpty()) return true; 
    T element_a = a.pop(); 
    T element_b = b.pop();
    try {
        if (((element_a==null) && (element_b!=null)) || (!element_a.equals(element_b)))
            return false;
        return compareStacks(a, b); 
    } finally { // restore elements
        a.push(element_a); 
        b.push(element_b);
    }
}

с рекурсией всегда помогает думать об этом как о 2 частях, "настройке" и рекурсивной функции. Ваша настройка создаст правильную ситуацию (создайте два стека, передайте их и т. д.), а затем вызовет рекурсивный метод, и когда рекурсивный метод будет выполнен, сообщите о результатах.

в вашем случае вам, вероятно, нужна эта подпись для "рекурсивного" метода:

public boolean compareStacks(Stack one, Stack two)

если этот метод pops & сравнивает верхние элементы буксировки стека, он может вернуть false прямо тогда (говоря, что они не сравнивают). Если да, то теперь у вас есть две стопки, каждая из которых короче, чем раньше. Вы уже знаете, как сравнить эти два стека, правильно (вы только что написали метод для этого!).

в конце вы можете "нажать" один элемент обратно в каждый стек, чтобы восстановить его предыдущее состояние перед возвратом.

будет немного хитрости в восстановлении стека в случае, когда они не сравниваются, и гарантируя, что если compareStack вы вызываете не удается правильно передать это до предыдущего состояния, даже если" текущий " compareStack преуспевает, но это детали реализации-просто подумал, что я упомянул бы их, чтобы вы не упускали их из виду.

есть симпатичное решение с Try / finally (нет улова, возврат изнутри try и возврат в стек в finally), которое сделало бы код довольно скользким, но это достаточно легко без него.