使用JavaScript中的两个堆栈实现队列数据结构:Rocket:
#javascript #堆栈 #dsa #queue

LeetCode Question
在此博客文章中,我们将探讨如何使用JavaScript中的两个堆栈实现队列数据结构。队列和堆栈是计算机科学中用于管理元素集合的基本数据结构。队列遵循第一个第一(FIFO)的原则,而堆栈遵循了最后的(LIFO)原理。通过使用两个堆栈,我们可以实现队列所需的FIFO行为。 ð§±

理解代码ðü

让我们从了解上面提供的代码开始。该代码定义了MyQueue类的构造函数函数,这将是我们使用两个堆栈实现的队列数据结构。这是供参考的代码段:

var MyQueue = function() {
    this.pushStack = [];
    this.popStack = [];
};

实施方式的运作方式 -

通过以下方法实现了使用两个堆栈的队列实现:

入住(x):

MyQueue.prototype.enqueue = function(x) {
    while (this.popStack.length) {
        this.pushStack.push(this.popStack.pop());
    }
    this.pushStack.push(x);
};

此方法用于在队列中添加一个元素x。为了维护FIFO行为,它首先将所有元素从Popstack转移到PushStack(以相反的顺序),然​​后将新元素推到PushStack。

Dequeue():

MyQueue.prototype.dequeue= function() {
    while (this.pushStack.length) {
        this.popStack.push(this.pushStack.pop());
    }
    return this.popStack.pop();
};

此方法用于脱水并返回队列的前元素(最古老的元素)。为此,它将所有元素从PUSTSTACK传输到Popstack(以相反的顺序),然​​后弹出并返回Popstack的顶部元素。

窥视():

MyQueue.prototype.peek = function() {
    while (this.pushStack.length) {
        this.popStack.push(this.pushStack.pop());
    }
    return this.popStack[this.popStack.length - 1];
};

此方法用于检索队列的前元元素而无需删除。与Dequeue()方法一样,它将所有元素从PUSTSTACK转移到Popstack(以相反顺序),并返回Popstack的顶部元素而不会弹出。

空的():

MyQueue.prototype.empty = function() {
    return !this.popStack.length && !this.pushStack.length;
};

此方法检查队列是否为空。如果PushStack和Popstack都是空的,它将返回true;否则,它返回false。

让我们测试代码

// Create a new instance of MyQueue
const queue = new MyQueue();

// Push elements into the Queue
queue.enqueue(1);
queue.enqueue(2);
queue.enqueue(3);

// Pop an element from the Queue
const poppedElement = queue.dequeue();
console.log("Popped element:", poppedElement); // Output: Popped element: 1

// Peek at the front element of the Queue
const frontElement = queue.peek();
console.log("Front element:", frontElement); // Output: Front element: 2

// Check if the Queue is empty
const isEmpty = queue.empty();
console.log("Is Queue empty?", isEmpty); // Output: Is Queue empty? false

优点和局限性

使用两个堆栈实现队列提供了几个优点:

  1. 它允许我们实现队列的FIFO行为,同时仍利用堆栈的有效推动和流行操作。

  2. 代码简单易懂,使其适合教育目的和小规模的实现。

但是,此实施有一些局限性:

  1. peek(),dequeue()和inqueue()方法在最坏情况下具有O(n)的时间复杂性,其中n是队列中的元素数量。这是由于需要在两个堆栈之间传输元素。

优化实施以实现入口操作

MyQueue.prototype.enqueue = function (x) {
  this.pushStack.push(x);
};

MyQueue.prototype.dequeue = function () {
  while (this.pushStack.length) {
    this.popStack.push(this.pushStack.pop());
  }
  const poppedItem = this.popStack.pop();
// move elements back to pushStack
  while (this.popStack.length) {
    this.pushStack.push(this.popStack.pop());
  }
  return poppedItem;
};

MyQueue.prototype.peek = function () {
  while (this.pushStack.length) {
    this.popStack.push(this.pushStack.pop());
  }
  const peekedItem = this.popStack[this.popStack.length - 1];
// move elements back to pushStack
  while (this.popStack.length) {
    this.pushStack.push(this.popStack.pop());
  }
  return peekedItem;
};

MyQueue.prototype.empty = function () {
  return !this.pushStack.length;
};

此实现通过在每个操作后将所有元素保留在推堆中。

优化实施dequeue操作

MyQueue.prototype.enqueue = function (x) {
  while (this.popStack.length) {
    this.pushStack.push(this.popStack.pop());
  }
  this.pushStack.push(x);
// move elements back to popStack
  while (this.pushStack.length) {
    this.popStack.push(this.pushStack.pop());
  }
};

MyQueue.prototype.dequeue = function () {
  return this.popStack.pop();
};

MyQueue.prototype.peek = function () {
  return this.popStack[this.popStack.length - 1];
};

MyQueue.prototype.empty = function () {
  return !this.popStack.length;
};

此实现通过在每个操作后保留POP堆栈中的所有元素来优化Dequeue操作。
它还将窥视操作视为按产品。

  1. 空()方法具有O(1)的时间复杂性,因为它仅检查两个堆栈是否为空。

结论ð

在此博客文章中,我们学会了如何使用JavaScript中的两个堆栈实现队列数据结构。我们探索了使我们能够利用堆栈的LIFO属性来维持队列的FIFO行为的代码。尽管此实现提供了一种简单直观的方式来创建队列,但要牢记潜在的性能影响很重要,尤其是在具有大量元素的情况下。

作为软件开发人员,了解数据结构及其实现对于编写有效和优化的代码至关重要。从头开始实施数据结构还可以提高您的解决问题的能力,并增强您设计更复杂算法的能力。 ð

可以随意尝试代码并探索进一步的优化以创建更有效的队列实现。愉快的编码! ð»