【JS】怎么用队列实现栈

题目

具体思路

  • 数据结构初始化:使用一个数组(模拟队列)来作为基础数据结构,在构造函数 MyStack 中初始化这个数组 queue,后续所有栈的操作都基于这个队列进行。

  • 入栈操作(push 方法):入栈操作相对简单直接,因为栈的入栈是在栈顶添加元素,对应到这里就是直接将元素添加到队列的末尾,使用 queue.push(x) 方法,这样新元素就进入了队列(模拟的栈)中。

  • 出栈操作(pop 方法):由于队列是先进先出,而栈是后进先出,为了实现栈的出栈效果,需要将队列中除了最后一个元素之外的所有元素依次出队(使用 queue.shift()),再重新入队到队列尾部(使用 queue.push())。经过这样的操作,原本在队列末尾的元素(即对应栈的栈顶元素)就会移动到队列头部,然后再将这个元素出队(queue.shift())并返回,从而实现了栈的出栈操作。

  • 获取栈顶元素操作(top 方法):为了获取栈顶元素但不改变栈的状态,先调用 pop 方法获取栈顶元素(此时元素已被 “移除”),然后再将该元素添加回队列(queue.push(x)),这样既获取到了栈顶元素,又保证了栈的状态不变。

  • 判断栈是否为空操作(empty 方法):直接检查队列的长度是否为 0,如果为 0 则说明栈中没有元素,即栈为空,返回 true;否则返回 false

出栈操作举例

假设我们有一个 MyStack 实例,其内部的 queue 队列初始状态为 [1, 2, 3, 4, 5] ,现在来执行 pop 方法:

  1. 首先获取队列的长度,let size = this.queue.length,此时 size 的值为 5

  2. 进入 while 循环,while (size-- > 1),判断条件 size-- > 1 等价于先判断 size > 1 ,然后再将 size 的值减 1 。

    • 第一次循环:

      • 初始 size 为 55 > 1 条件成立,进入循环体。
      • 执行 this.queue.push(this.queue.shift())this.queue.shift() 会从队列头部移除元素 1 并返回,然后 this.queue.push(返回值) 会将返回的元素 1 添加到队列尾部。此时队列变为 [2, 3, 4, 5, 1] 。
      • 执行 size--size 的值变为 4
    • 第二次循环:

      • 4 > 1 条件成立,进入循环体。
      • 执行 this.queue.push(this.queue.shift())this.queue.shift() 从队列头部移除元素 2 并返回,然后将 2 添加到队列尾部,此时队列变为 [3, 4, 5, 1, 2] 。
      • 执行 size--size 的值变为 3
    • 第三次循环:

      • 3 > 1 条件成立,进入循环体。
      • 执行 this.queue.push(this.queue.shift())this.queue.shift() 从队列头部移除元素 3 并返回,然后将 3 添加到队列尾部,此时队列变为 [4, 5, 1, 2, 3] 。
      • 执行 size--size 的值变为 2
    • 第四次循环:

      • 2 > 1 条件成立,进入循环体。
      • 执行 this.queue.push(this.queue.shift())this.queue.shift() 从队列头部移除元素 4 并返回,然后将 4 添加到队列尾部,此时队列变为 [5, 1, 2, 3, 4] 。
      • 执行 size--size 的值变为 1
  3. 此时 size 变为 11 > 1 条件不成立,while 循环结束。

  4. 执行 return this.queue.shift(),此时队列头部的元素 5 被移除并返回,实现了栈的 “出栈” 操作(因为栈是后进先出,这里原本在队列末尾的 5 经过一系列操作后成为了第一个被移除的元素,符合栈的特性)。

示例代码

// 使用一个队列实现栈的功能
// 定义一个名为MyStack的构造函数,用于创建栈对象
/**
 * 初始化你的数据结构
 */
var MyStack = function() {
    // 使用一个数组queue来模拟队列,后续将基于这个队列实现栈的操作
    this.queue = [];
};

/**
 * 将元素x压入栈中
 * @param {number} x - 要压入栈的元素
 * @return {void} - 该方法没有返回值
 */
MyStack.prototype.push = function(x) {
    // 直接将元素x添加到队列的末尾,模拟栈的入栈操作
    this.queue.push(x);
};

/**
 * 移除栈顶元素并返回该元素
 * @return {number} - 返回移除的栈顶元素
 */
MyStack.prototype.pop = function() {
    // 获取当前队列的长度
    let size = this.queue.length;
    // 当队列长度大于1时,将队列头部的元素依次出队并重新入队到队列尾部
    // 这样操作后,最后一个元素就会留在队列头部,即原本的栈顶元素
    while (size-- > 1) {
        this.queue.push(this.queue.shift());
    }
    // 移除并返回队列头部的元素,即栈顶元素
    return this.queue.shift();
};

/**
 * 获取栈顶元素,但不将其移除
 * @return {number} - 返回栈顶元素
 */
MyStack.prototype.top = function() {
    // 调用pop方法获取栈顶元素,此时元素被移除
    const x = this.pop();
    // 将获取到的元素重新添加到队列中,保证栈的状态不变
    this.queue.push(x);
    // 返回获取到的栈顶元素
    return x;
};

/**
 * 判断栈是否为空
 * @return {boolean} - 如果栈为空返回true,否则返回false
 */
MyStack.prototype.empty = function() {
    // 当队列的长度为0时,说明栈中没有元素,即栈为空
    return!this.queue.length;
};

欢迎指正!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值