Средний элемент в стеке

1

Я прочитал статью о реализации стека в javascript и python на сайте geeksforgeeks. Я реализовал код для удаления среднего элемента в стеке в javascript точно так же, как это дано для python на том же сайте. Но я получаю неправильный ответ. Почему это так? в чем разница между двумя языками в этом случае? Как я могу получить правильный ответ в JavaScript? Ниже приведен код в Javascript.

class Stack {
  constructor() {
    this.items = [];
  }

  push(element) {
    this.items.push(element);
  }

  pop() {
    if (this.items.length === 0) {
      return "Underflow";
    } else {
      return this.items.pop();
    }
  }

  peek() {
    return this.items[this.items.length - 1];
  }

  isEmpty() {
    return this.items.length == 0;
  }
  print() {
    console.log(this.items);
  }
}

function deleteMid(stack, curr) {

  // If stack is empty or all items 
  // are traversed 

  if (stack.isEmpty() || curr == stack.items.length) {
    return;
  }
  // Remove last item
  x = stack.peek();
  stack.pop();

  // Remove other items 
  deleteMid(stack, curr + 1);
  console.log("length value: ", stack.items.length);

  // Put all items back except middle 
  if (curr != Math.floor(stack.length / 2)) {
    stack.push(x);
  }
}

var stack = new Stack();
stack.push(1);
stack.push(2);
stack.push(3);
stack.print();
deleteMid(stack, 0);
stack.print();
  • 0
    geeksforgeeks.org/delete-middle-element-stack
  • 0
    Можете ли вы опубликовать вывод, который вы получаете?
Показать ещё 1 комментарий
Теги:
data-structures
stack

2 ответа

1
Лучший ответ

Есть некоторые части реализации Python, которые ваша реализация пропускает:

У вас есть неявно глобальная переменная x - в отличие от Python, в Javascript переменные, объявленные без var/let/const, назначаются глобальному объекту, поэтому после завершения рекурсивного deleteMid только одна переменная с именем x (а не одна для каждой итерации), который вы переназначали каждый раз. Вместо этого используйте const x, чтобы каждый вызов deleteMid имел собственную привязку x.

У вашего стека нет свойства length, поэтому результаты теста curr != Math.floor(stack.length/2) в curr != NaN - это не то, что вам нужно. Хотя вы могли бы дать свой stack свойство getter length:

  get length() {
    return this.items.length;
  }

это все еще не соответствует реализации Python, которая непрерывно рекурсивно передает начальную длину в качестве другого аргумента: если вы хотите имитировать реализацию Python, сделайте это тоже с переменной n:

function deleteMid(stack, n, curr) {
  // ...
  // Remove other items 
  deleteMid(stack, n, curr + 1);
  // Put all items back except middle 
  if (curr != Math.floor(n / 2)) {
  // ...
// Call with:
deleteMid(stack, stack.items.length, 0);

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

По той же причине, для того чтобы стеки работали даже разного размера, нам также нужно изменить ваш тест JS здесь:

if (stack.isEmpty() || curr == stack.items.length) {

соответствовать коду Python:

if (st.isEmpty() or curr == n) :

Рабочий код:

class Stack {
  constructor() {
    this.items = [];
  }

  push(element) {
    this.items.push(element);
  }

  pop() {
    if (this.items.length === 0) {
      return "Underflow";
    } else {
      return this.items.pop();
    }
  }

  peek() {
    return this.items[this.items.length - 1];
  }

  isEmpty() {
    return this.items.length == 0;
  }
  print() {
    console.log(this.items);
  }
  get length() {
    return this.items.length;
  }
}

function deleteMid(stack, n, curr) {

  // If stack is empty or all items 
  // are traversed 

  if (stack.isEmpty() || curr === n) {
    return;
  }
  // Remove last item
  const x = stack.peek();
  stack.pop();

  // Remove other items 
  deleteMid(stack, n, curr + 1);

  // Put all items back except middle 
  if (curr != Math.floor((n) / 2)) {
    stack.push(x);
  }
}

var stack = new Stack();
stack.push(1);
stack.push(2);
stack.push(3);
stack.print();
deleteMid(stack, stack.items.length, 0);
stack.print();
  • 0
    Спасибо за объяснение. Причина, по которой я не передал параметр 'n', заключается в том, что я думал, что stack.items.length останется неизменным, и поэтому я мог передавать только параметры стека и индекса.
1

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

class Stack {
  constructor() {
    this.items = [];
  }

  push(element) {
    this.items.push(element);
  }

  pop() {
    if (this.items.length === 0) {
      return "Underflow";
    } else {
      return this.items.pop();
    }
  }

  peek() {
    return this.items[this.items.length - 1];
  }

  isEmpty() {
    return this.items.length == 0;
  }
  print() {
    console.log(this.items);
  }
}

function deleteMid(stack, middle = Math.round(stack.items.length / 2)) {
  if (stack.isEmpty()) return;
  
  const isMiddle = stack.items.length === middle;
  
  // Remove last item
  const x = stack.pop();

  // stop when you get to the middle
  if (isMiddle) return;
  
  // Remove other items
  deleteMid(stack, middle);
  
  // add the item back
  stack.push(x);
}

var stack = new Stack();
stack.push(1);
stack.push(2);
stack.push(3);
stack.print();
deleteMid(stack);
stack.print();
  • 0
    Спасибо. Понял! Я пробовал этот подход раньше, но я не получил правильный ответ. Я все еще привыкаю к Javascript способу программирования!
  • 0
    Можете ли вы объяснить, что происходит на этой линии? const isMiddle = stack.items.length === middle;
Показать ещё 2 комментария

Ещё вопросы

Сообщество Overcoder
Наверх
Меню