225. 用队列实现栈

请你仅使用两个队列实现一个后入先出 (LIFO) 的栈, 并支持普通栈的全部四种操作 (push, top, pop 和 empty) .

实现 MyStack 类:

  • void push(int x) 将元素 x 压入栈顶.
  • int pop() 移除并返回栈顶元素.
  • int top() 返回栈顶元素.
  • boolean empty() 如果栈是空的, 返回 true , 否则, 返回 false .

注意:

  • 你只能使用队列的标准操作 —— 也就是 push to back, peek/pop from front, size 和 is empty 这些操作.
  • 你所使用的语言也许不支持队列. 你可以使用 list (列表) 或者 deque (双端队列) 来模拟一个队列 , 只要是标准的队列操作即可.

示例:

输入:

["MyStack", "push", "push", "top", "pop", "empty"]
[[], [1], [2], [], [], []]

输出:

[null, null, null, 2, 2, false]

解释:

MyStack myStack = new MyStack();
myStack.push(1);
myStack.push(2);
myStack.top(); // 返回 2
myStack.pop(); // 返回 2
myStack.empty(); // 返回 False

提示:

  • 1 <= x <= 9
  • 最多调用 100 次 push, pop, top 和 empty
  • 每次调用 pop 和 top 都保证栈不为空

进阶: 你能否仅用一个队列来实现栈.

用两个队列模拟栈

思路:

从一个队列把数据导入另一个队列时, 数据的顺序没有发生变化.
用两个队列来模拟栈时, 一个队列负责主要工作, 另一个队列负责在模拟弹栈操作时备份数据, 起辅助作用.
模拟弹栈操作时, 将队列1的除了队尾元素外的所有元素出队, 并入队至队列2中. 此时队列1的top指针就指向这个要弹栈的元素了. 弹出这个元素后, 再把队列2的全部元素出队并入队队列1.
只有模拟弹栈操作时才会用到队列2, 其余操作只需要队列1.



代码:

#define MAXSIZE 100
typedef struct {
int* queue1;
int* queue2;
int top1, top2, rear1, rear2;
} MyStack;
MyStack* myStackCreate() {
MyStack* mystack = (MyStack*)malloc(sizeof(MyStack));
mystack->queue1 = (int*)malloc(sizeof(int) * MAXSIZE);
mystack->queue2 = (int*)malloc(sizeof(int) * MAXSIZE);
mystack->top1 = 0;
mystack->top2 = 0;
mystack->rear1 = 0;
mystack->rear2 = 0;
return mystack;
}
// 入栈, 就是队列1的入队
void myStackPush(MyStack* obj, int x) {
obj->queue1[obj->rear1] = x;
obj->rear1 = (obj->rear1 + 1) % MAXSIZE;
}
// 弹栈
int myStackPop(MyStack* obj) {
// 第一步, 备份
while ((obj->top1 + 1) % MAXSIZE != obj->rear1) {
obj->queue2[obj->rear2] = obj->queue1[obj->top1];
obj->rear2 = (obj->rear2 + 1) % MAXSIZE;
obj->top1 = (obj->top1 + 1) % MAXSIZE;
}
// 第二步, 弹栈
int val = obj->queue1[obj->top1];
obj->top1 = (obj->top1 + 1) % MAXSIZE;
// 第三步, 备份复原
while ((obj->top2) != (obj->rear2)) {
obj->queue1[obj->rear1] = obj->queue2[obj->top2];
obj->rear1 = (obj->rear1 + 1) % MAXSIZE;
obj->top2 = (obj->top2 + 1) % MAXSIZE;
}
return val;
}
// 取栈顶元素, 就是队列的尾元素
int myStackTop(MyStack* obj) {
return obj->queue1[(obj->rear1 - 1 + MAXSIZE) % MAXSIZE];
}
// 判断栈是否为空
bool myStackEmpty(MyStack* obj) {
if (obj->rear1 == obj->top1)
return true;
else
return false;
}
// 销毁栈
void myStackFree(MyStack* obj) {
obj->top2 = 0;
obj->rear2 = 0;
free(obj->queue2);
obj->top1 = 0;
obj->rear1 = 0;
free(obj->queue1);
}
/**
* Your MyStack struct will be instantiated and called as such:
* MyStack* obj = myStackCreate();
* myStackPush(obj, x);
* int param_2 = myStackPop(obj);
* int param_3 = myStackTop(obj);
* bool param_4 = myStackEmpty(obj);
* myStackFree(obj);
*/

用一个队列模拟栈

思路:

与用两个队列模拟栈的区别仅在于弹栈操作. 弹栈前, 将队列的头元素依次放到队列尾即可.

代码:

#define MAXSIZE 100
typedef struct {
int* queue;
int top, rear;
} MyStack;
MyStack* myStackCreate() {
MyStack* mystack = (MyStack*)malloc(sizeof(MyStack));
mystack->queue = (int*)malloc(sizeof(int) * MAXSIZE);
mystack->top = 0;
mystack->rear = 0;
return mystack;
}
void myStackPush(MyStack* obj, int x) {
obj->queue[obj->rear] = x;
obj->rear = (obj->rear + 1) % MAXSIZE;
}
int myStackPop(MyStack* obj) {
// 因为下面的代码导致rear在变化,所以要保存这个初始的rear
int tmp = obj->rear;
while ((obj->top + 1) % MAXSIZE != tmp) {
obj->queue[obj->rear] = obj->queue[obj->top];
obj->rear = (obj->rear + 1) % MAXSIZE;
obj->top = (obj->top + 1) % MAXSIZE;
}
int val = obj->queue[obj->top];
obj->top = (obj->top + 1) % MAXSIZE;
return val;
}
int myStackTop(MyStack* obj) {
return obj->queue[(obj->rear - 1 + MAXSIZE) % MAXSIZE];
}
bool myStackEmpty(MyStack* obj) {
if (obj->rear == obj->top)
return true;
else
return false;
}
void myStackFree(MyStack* obj) {
obj->top = 0;
obj->rear = 0;
free(obj->queue);
}
/**
* Your MyStack struct will be instantiated and called as such:
* MyStack* obj = myStackCreate();
* myStackPush(obj, x);
* int param_2 = myStackPop(obj);
* int param_3 = myStackTop(obj);
* bool param_4 = myStackEmpty(obj);
* myStackFree(obj);
*/
posted @   有空  阅读(7)  评论(0编辑  收藏  举报
编辑推荐:
· 如何编写易于单元测试的代码
· 10年+ .NET Coder 心语,封装的思维:从隐藏、稳定开始理解其本质意义
· .NET Core 中如何实现缓存的预热?
· 从 HTTP 原因短语缺失研究 HTTP/2 和 HTTP/3 的设计差异
· AI与.NET技术实操系列:向量存储与相似性搜索在 .NET 中的实现
阅读排行:
· 10年+ .NET Coder 心语 ── 封装的思维:从隐藏、稳定开始理解其本质意义
· 地球OL攻略 —— 某应届生求职总结
· 周边上新:园子的第一款马克杯温暖上架
· Open-Sora 2.0 重磅开源!
· 提示词工程——AI应用必不可少的技术
点击右上角即可分享
微信分享提示

目录导航