✨✨欢迎大家来到Celia的博客✨✨
🎉🎉创作不易,请点赞关注,多多支持哦🎉🎉
所属专栏:OJ题
目录
一、题目
请你仅使用两个栈实现先入先出队列。队列应当支持一般队列支持的所有操作(
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(双端队列)来模拟一个栈,只要是标准的栈操作即可。
题目:用栈实现队列
二、解题思路
在开始构思之前,我们需要明确栈和队列的区别:
- 栈:先进后出
- 队列:先进先出
题目要求用两个栈来实现队列,由于栈和队列的进出规则不同,最关键的点在于如何处理栈和队列进出数据顺序的问题。
栈实现队列,模拟队列出队需要拿出栈底的元素,我们可以利用两个栈之间的数据交换来实现
- 假设栈中有n个元素
- 利用循环先把栈1中的前n - 1个元素移动到栈2当中
- 把栈1中剩余的一个元素出栈
- 再将栈2中的元素放回到栈1当中
- 成功模拟队列出队等操作
三、代码实现(栈完整代码 + 模拟代码)
// 支持动态增长的栈 typedef int STDataType; typedef struct Stack { STDataType* _a; int _top; // 栈顶 int _capacity; // 容量 }Stack; // 初始化栈 void StackInit(Stack* ps); // 入栈 void StackPush(Stack* ps, STDataType data); // 出栈 void StackPop(Stack* ps); // 获取栈顶元素 STDataType StackTop(Stack* ps); // 获取栈中有效元素个数 int StackSize(Stack* ps); // 检测栈是否为空,如果为空返回非零结果,如果不为空返回0 int StackEmpty(Stack* ps); // 销毁栈 void StackDestroy(Stack* ps); // 初始化栈 void StackInit(Stack* ps) { assert(ps); ps->_a = NULL; ps->_capacity = ps->_top = 0; } // 销毁栈 void StackDestroy(Stack* ps) { assert(ps); free(ps->_a); ps->_a = NULL; ps->_capacity = ps->_top = 0; } // 入栈 void StackPush(Stack* ps, STDataType data) { assert(ps); if (ps->_top == ps->_capacity) { int newcapacity = ps->_capacity == 0 ? 4 : ps->_capacity + (ps->_capacity >> 1); STDataType* newnode = (STDataType*)realloc(ps->_a, newcapacity * sizeof(STDataType)); if (newnode == NULL) perror("StackPush()::realloc()\n"); else { ps->_a = newnode; ps->_capacity = newcapacity; } } ps->_a[ps->_top++] = data; } // 出栈 void StackPop(Stack* ps) { assert(ps); if (!ps->_top) { printf("栈为空\n"); return; } else ps->_top--; } // 获取栈顶元素 STDataType StackTop(Stack* ps) { assert(ps); assert(ps->_top > 0); return ps->_a[ps->_top - 1]; } // 获取栈中有效元素个数 int StackSize(Stack* ps) { assert(ps); return ps->_top; } // 检测栈是否为空,如果为空返回非零结果,如果不为空返回0 int StackEmpty(Stack* ps) { assert(ps); return !ps->_top; } /*=============================== 模拟队列 ===========================*/ typedef struct { Stack s1;//栈1 Stack s2;//栈2 } MyQueue; //建立模拟队列 MyQueue* myQueueCreate() { MyQueue* q = (MyQueue*)malloc(sizeof(MyQueue)); StackInit(&q->s1); StackInit(&q->s2); return q; } //在非空的一个栈中入栈 void myQueuePush(MyQueue* obj, int x) { if (!StackEmpty(&obj->s1)) StackPush(&obj->s1,x); else StackPush(&obj->s2,x); } //删除模拟队列的队头元素 int myQueuePop(MyQueue* obj) { Stack* empty = &obj->s1; Stack* nonempty = &obj->s2; if(StackEmpty(&obj->s2)) { empty = &obj->s2; nonempty = &obj->s1; } while(StackSize(nonempty) > 1)//移动n-1个元素 { StackPush(empty,StackTop(nonempty));//对空栈入栈 StackPop(nonempty);//删除非空栈栈顶的元素 } int top = StackTop(nonempty);记录栈底(队头)的元素 StackPop(nonempty);//删除 while(StackSize(empty) > 0)//放回剩余元素 { StackPush(nonempty,StackTop(empty)); StackPop(empty); } return top;//返回被删除的元素 } //取出模拟队列队头元素,思路与删除相同,但是不删除最后一个元素,仅仅是记录 int myQueuePeek(MyQueue* obj) { Stack* empty = &obj->s1; Stack* nonempty = &obj->s2; if(StackEmpty(&obj->s2)) { empty = &obj->s2; nonempty = &obj->s1; } while(StackSize(nonempty) > 1) { StackPush(empty,StackTop(nonempty)); StackPop(nonempty); } int top = StackTop(nonempty); StackPush(empty,StackTop(nonempty)); StackPop(nonempty); while(StackSize(empty) > 0) { StackPush(nonempty,StackTop(empty)); StackPop(empty); } return top; } //判空 bool myQueueEmpty(MyQueue* obj) { return StackEmpty(&obj->s1) && StackEmpty(&obj->s2); } //销毁 void myQueueFree(MyQueue* obj) { StackDestroy(&obj->s1); StackDestroy(&obj->s2); free(obj); }