题目
具体思路
-
数据结构初始化:使用一个数组(模拟队列)来作为基础数据结构,在构造函数
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
方法:
首先获取队列的长度,
let size = this.queue.length
,此时size
的值为5
。进入
while
循环,while (size-- > 1)
,判断条件size-- > 1
等价于先判断size > 1
,然后再将size
的值减1
。
第一次循环:
- 初始
size
为5
,5 > 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
。此时
size
变为1
,1 > 1
条件不成立,while
循环结束。执行
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;
};
欢迎指正!