用队列实现栈
- 题目
- 解题思路
- 1. `push`
- 2. `pop`
- 3. `empty`
- Code
- Queue.h
- Queue.c
- Stack.c
题目
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(双端队列)来模拟一个队列 , 只要是标准的队列操作即可。注意:
-
你只能使用队列的标准操作 —— 也就是
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
解题思路
使用两个队列 queue1
和 queue2
来模拟栈的行为。队列遵循先进先出(FIFO)原则,而栈遵循后进先出(LIFO)原则,所以需要通过特定的操作来转换这种特性。
1. push
- 目的:将元素
x
压入栈顶。 - 思路:选择非空队列(如果两个队列都为空,则任选一个),将
x
加入该队列的尾部。
2. pop
- 目的:移除并返回栈顶元素。
- 思路:
- 队列是 FIFO ,栈顶元素在队列的尾部。要将除了最后一个元素之外的其他元素都移动到另一个队列中。将
nonempty
中的元素依次出队并加入到empty
中,直到nonempty
中只剩下一个元素,这个元素就是栈顶元素。 - 将
nonempty
中剩下的这个元素出队并返回。
- 队列是 FIFO ,栈顶元素在队列的尾部。要将除了最后一个元素之外的其他元素都移动到另一个队列中。将
3. empty
- 目的:判断栈是否为空。
- 思路:由于栈是由两个队列模拟的,当两个队列都为空时,栈才为空。所以只需要检查
queue1
和queue2
是否都为空即可。
Code
Queue.h
typedef int QDataType;
typedef struct QueueNode
{
struct QueueNode* next;
QDataType data;
}QNode;
typedef struct Queue
{
QNode* phead;
QNode* ptail;
int size;
}Queue;
void QueueInit(Queue* pq);
void QueueDestory(Queue* pq);
void QueuePush(Queue* pq, QDataType x);
void QueuePop(Queue* pq);
QDataType QueueFront(Queue* pq);
QDataType QueueBack(Queue* pq);
int QueueSize(Queue* pq);
bool QueueEmpty(Queue* pq);
Queue.c
void QueueInit(Queue* pq) {
assert(pq);
pq->phead = NULL;
pq->ptail = NULL;
pq->size = 0;
}
void QueueDestory(Queue* pq) {
assert(pq);
QNode* cur = pq->phead;
while (cur) {
QNode* next = cur->next;
free(cur);
cur = next;
}
pq->phead = pq->ptail = NULL;
pq->size = 0;
}
void QueuePush(Queue* pq, QDataType x) {
assert(pq);
QNode* newnode = (QNode*)malloc(sizeof(QNode));
if (newnode == NULL) {
perror("malloc fail\n");
return;
}
newnode->data = x;
newnode->next = NULL;
if (pq->ptail == NULL) {
assert(pq->phead == NULL);
pq->phead = pq->ptail = newnode;
}
else {
pq->ptail->next = newnode;
pq->ptail = newnode;
}
pq->size++;
}
void QueuePop(Queue* pq) {
assert(pq);
assert(!QueueEmpty(pq));
// one node
if (pq->phead->next == NULL) {
free(pq->phead);
pq->phead = pq->ptail = NULL;
}
// more node
else {
QNode* next = pq->phead->next;
free(pq->phead);
pq->phead = next;
}
pq->size--;
}
QDataType QueueFront(Queue* pq) {
assert(pq);
assert(!QueueEmpty(pq));
return pq->phead->data;
}
QDataType QueueBack(Queue* pq) {
assert(pq);
assert(!QueueEmpty(pq));
return pq->ptail->data;
}
int QueueSize(Queue* pq) {
assert(pq);
return pq->size;
}
bool QueueEmpty(Queue* pq) {
assert(pq);
//return pq->phead == NULL && pq->ptail == NULL;
return pq->size == 0;
}
Stack.c
typedef struct {
Queue q1;
Queue q2;
} MyStack;
MyStack* myStackCreate() {
MyStack* obj = (MyStack*)malloc(sizeof(MyStack));
if(obj == NULL){
perror("malloc fail");
return NULL;
}
QueueInit(&obj->q1);
QueueInit(&obj->q2);
return obj;
}
void myStackPush(MyStack* obj, int x) {
if(!QueueEmpty(&obj->q1)){
QueuePush(&obj->q1, x);
}else{
QueuePush(&obj->q2, x);
}
}
int myStackPop(MyStack* obj) {
Queue* pEmptyQ = &obj->q1;
Queue* pNonEmptyQ = &obj->q2;
if(!QueueEmpty(&obj->q1)){
pEmptyQ = &obj->q2;
pNonEmptyQ = &obj->q1;
}
while(QueueSize(pNonEmptyQ)>1){
QueuePush(pEmptyQ,QueueFront(pNonEmptyQ));
QueuePop(pNonEmptyQ);
}
int top = QueueBack(pNonEmptyQ);
QueuePop(pNonEmptyQ);
return top;
}
int myStackTop(MyStack* obj) {
if(!QueueEmpty(&obj->q1)){
return QueueBack(&obj->q1);
}else{
return QueueBack(&obj->q2);
}
}
bool myStackEmpty(MyStack* obj) {
return QueueEmpty(&obj->q1)
&& QueueEmpty(&obj->q2);
}
void myStackFree(MyStack* obj) {
QueueDestory(&obj->q1);
QueueDestory(&obj->q2);
free(obj);
}