【问题标题】:Middle element in stack堆栈中的中间元素
【发布时间】:2019-05-20 17:39:09
【问题描述】:

我在 geeksforgeeks 网站上阅读了关于在 javascript 和 python 中实现堆栈的文章。我实现了代码以在 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();

【问题讨论】:

标签: javascript data-structures stack


【解决方案1】:

您的实现遗漏了 Python 实现的某些部分:

您有一个隐式全局 x 变量 - 与 Python 不同,在 Javascript 中,未声明 var / let / const 的变量被分配给全局对象,因此一旦递归 deleteMids 完成,只有一个名为 x 的变量(而不是每次迭代一个),您每次都重新分配了它。请改用const x,以确保deleteMid 的每个调用都有自己的x 绑定。

您的堆栈没有length 属性,因此您的curr != Math.floor(stack.length/2) 测试结果为curr != NaN - 这不是您想要的。虽然你可以给你的 stack length getter 属性:

  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();

【讨论】:

  • 感谢您的解释。我没有传递参数 'n' 的原因是我认为 stack.items.length 会保持不变,所以我只能传递堆栈和索引参数。
【解决方案2】:

由于您在开始时知道中间索引,因此您可以在删除每个项目后检查堆栈的长度,并在您到达中间时停止。

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();

【讨论】:

  • 谢谢。知道了!我以前尝试过这种方法,但没有得到正确的答案。我还在习惯 Javascript 的编程方式!
  • 你能解释一下这行发生了什么吗? const isMiddle = stack.items.length === middle;
  • `stack.items.length === middle`是一个布尔表达式(返回truefalse),表达式的结果赋值给isMiddle
  • 好的!谢谢!明白了。就像返回真假并赋值一样。
猜你喜欢
  • 1970-01-01
  • 2020-08-03
  • 1970-01-01
  • 2010-10-28
  • 1970-01-01
  • 2021-08-06
  • 2013-11-07
  • 2016-06-29
  • 2014-07-26
相关资源
最近更新 更多