栈实现队列
介绍
题目来源
题目来源于力扣网站:栈实现队列
原理讲解
根据要求,只能使用标准的栈操作实现队列,关于标准的栈操作可以看我写过的文章:栈
我们知道,栈是先进后出,而队列是先进先出,所以毫无疑问,仅用一个栈没办法实现队列
进一步考虑,栈的出入顺序是相反的,所以如果将出栈顺序逆序,就实现了先进先出,因此可以使用两个栈来达到这个效果
上图用栈操作来讲解就是,队列尾插,相当于对pushst入栈,然后将pushst出栈同时对popst入栈,当队列头删时,相当于popst出栈
以上是基本原理,接下来我们用代码实现这个队列
代码实现
栈的基本操作如下
1 | typedef int STDataType; |
队列结构
1 | //MyQueue |
初始化
初始化一个队列,返回队列的指针
1.申请空间
2.将队列里两个栈初始化
3.返回队列的指针
1 | MyQueue* myQueueCreate() { |
销毁
销毁队列占用的空间,传入队列的指针
1.销毁两个栈
2.释放队列指针
1 | void myQueueFree(MyQueue* obj) { |
尾插
尾插新数据,传入队列指针和新数据x
根据前文中讲的原理,对队列尾插相当于对pushst入栈,因此直接调用入栈函数即可
1 | void myQueuePush(MyQueue* obj, int x) { |
头删
队列头删,传队列指针,返回队头元素
根据上述原理,队列头删相当于popst出栈
popst的顶端元素就是队列的队头元素,根据题目要求,头删时返回队头元素
因此首先判断popst是否为空
如果popst为空,就将pushst里的所有数据先出栈,再入栈到popst
接下来用ret接收popst的顶端元素,再对popst执行出栈
最后返回ret
1 | int myQueuePop(MyQueue* obj) { |
返回队头数据
获取队头元素,传入队列指针
这个函数来源于上面头删函数,但是不需要对popst出栈
1 | int myQueuePeek(MyQueue* obj) { |
判空
判断队列是否为空,返回bool值
当队列中两个栈都为空时,队列就是空,因此用逻辑与对两个栈判空即可
1 | bool myQueueEmpty(MyQueue* obj) { |
总结
问题的突破关键在于,栈遵守先进后出的原则,队列遵守先进先出的原则,栈可以逆序数据,两个栈就是两次逆序,两次逆序后顺序不变,从而实现了队列的原则
在尾插时对pushst入栈,在头删时对popst出栈,两个栈互不干扰
只有当popst为空时,才需要将pushst的数据压入popst
最后这是代码的通过截图