1 题目描述
LeetCode原题链接:232. 用栈实现队列
请你仅使用两个栈实现先入先出队列。队列应当支持一般队列支持的所有操作(push、pop、peek、empty):
实现 MyQueue 类:
- void push(int x) 将元素 x 推到队列的末尾
- int pop() 从队列的开头移除并返回元素
- int peek() 返回队列开头的元素
- boolean empty() 如果队列为空,返回 true ;否则,返回 false
说明:
- 你只能使用标准的栈操作 —— 也就是只有 push to top, peek/pop from top, size, 和 is empty 操作是合法的。
- 你所使用的语言也许不支持栈。你可以使用 list 或者 deque(双端队列)来模拟一个栈,只要是标准的栈操作即可。
提示:
- 1 <= x <= 9
- 最多调用 100 次 push、pop、peek 和 empty
- 假设所有操作都是有效的 (例如,一个空的队列不会调用 pop 或者 peek 操作)
2 解题思路及代码
2.1 C语言实现
/**
* @note
* 1. 构造两个栈, 一个栈用于入队, 一个栈用于出队
* 2. 队头指针指向出队栈, 队尾指针指向入队栈(头删尾插)
* 3. 当出队栈为空时, 将入队栈的数据全部弹出并压入出队栈
*/
// 最多调用100次, 故采用顺序栈
typedef struct{ // 也可用base与top指针构造顺序栈
int *stk;
int size;
int capacity;
}Stack;
Stack* stackCreate(int capacity){
Stack* ret = (Stack*)malloc(sizeof(Stack));
ret->stk = malloc(sizeof(int) * capacity);
ret->size = 0;
ret->capacity = capacity;
return ret;
}
void stackPush(Stack* obj, int x){ // 数组容量为测试最大次数, 故无需考虑栈满情况
if(obj->size < obj->capacity){
obj->stk[obj->size++] = x;
}
}
bool isStackEmpty(Stack* obj){
return obj->size == 0;
}
void stackPop(Stack* obj){ // 弹栈
obj->size--;
}
int stackTop(Stack* obj){ // 取栈顶元素
return obj->stk[obj->size - 1];
}
void stackFree(Stack* obj){
free(obj->stk);
}
typedef struct {
Stack* front;
Stack* rear
} MyQueue;
MyQueue* myQueueCreate() {
MyQueue* ret = (MyQueue*)malloc(sizeof(MyQueue));
ret->front = stackCreate(100);
ret->rear = stackCreate(100);
return ret;
}
void stackInToOut(MyQueue* obj){
while(!isStackEmpty(obj->rear)){
stackPush(obj->front, stackTop(obj->rear));
stackPop(obj->rear);
}
}
void myQueuePush(MyQueue* obj, int x) {
stackPush(obj->rear, x);
}
int myQueuePop(MyQueue* obj) { // 出队(需记录出队元素)
if(isStackEmpty(obj->front)){
stackInToOut(obj);
}
int x = stackTop(obj->front);
stackPop(obj->front);
return x;
}
int myQueuePeek(MyQueue* obj) { // 取队头元素
if(isStackEmpty(obj->front)){
stackInToOut(obj);
}
return stackTop(obj->front);
}
bool myQueueEmpty(MyQueue* obj) {
return (isStackEmpty(obj->front) && isStackEmpty(obj->rear));
}
void myQueueFree(MyQueue* obj) {
stackFree(obj->front);
stackFree(obj->rear);
}
复杂度分析:
-
时间复杂度:均摊复杂度 O(1),最坏情况下的时间复杂度 O(n)。
入队操作每次都将新元素直接压入至入队栈,时间复杂度O(1);出队操作时,当出队栈非空时,直接从栈顶弹出1个元素即可,若为空则需将入队栈n个元素全部弹出并压至出队栈,再从出队栈的栈顶弹出元素,因为出队栈为空出现频率较低,所以均摊后复杂度为O(n)。 -
空间复杂度:O(n),队列中最多存储n个元素。
2.2 C++语言实现
// 使用stack容器,具体实现思路同C
class MyQueue {
public:
stack<int> in_stk; // 入队栈
stack<int> out_stk; // 出队栈
MyQueue() {
}
void inToOut(){
if(out_stk.empty()){
while(!in_stk.empty()){
out_stk.push(in_stk.top());
in_stk.pop();
}
}
}
void push(int x) {
in_stk.push(x);
}
int pop() {
inToOut();
int x = out_stk.top();
out_stk.pop();
return x;
}
int peek() {
inToOut();
return out_stk.top();
}
bool empty() {
return in_stk.empty() && out_stk.empty();
}
};
2.3 Python3语言实现
#解题思路同C,只不过将列表当做栈来使用
class MyQueue:
def __init__(self):
self.front = []
self.rear = []
def stack_in_out(self):
if not self.front:
while self.rear:
self.front.append(self.rear.pop())
def push(self, x: int) -> None:
self.rear.append(x)
def pop(self) -> int:
self.stack_in_out()
return self.front.pop()
def peek(self) -> int:
self.stack_in_out()
if self.front:
return self.front[-1]
else:
return 0
def empty(self) -> bool:
return not (bool(self.front) or bool(self.rear))
END