![6c38cb5bf7bc38edc8137471991a59be.png](https://i-blog.csdnimg.cn/blog_migrate/34b6829238a9eb311b5cd83c5bf0591f.jpeg)
前言
栈和队列是算法的一个基本的知识点之一。这篇文章主要介绍三道有关栈和队列的算法题。因为篇幅所限,只介绍push和pop这两种方法的实现
- 用栈实现队列
- 用队列实现栈
- 循环队列的实现
用栈实现队列
入队列的功能我们可以用栈的入栈的功能替代。但问题在于出队列的功能怎么实现。
这里有一个问题,就是栈是后入先出的,队列是先进先出的,两者出入的方式不一样。
那么怎么实现方向的一致呢? 我们可以使用两个栈,一个栈用于输入,一个栈用于输出。当发现输出栈为空的时候,把排列的数据从输入栈一个个弹出,“倒入”到 输出栈中,这样的话,数据排列的方向就刚好被逆转过来了,原本在输入栈中处于栈底的数据被置换到输出栈的栈顶,这时候对它出栈也就同时完成了队列的出列的功能。
下面是具体的图示
1.入队列操作: 等同于对入队列进行入栈操作,图示如下
![fb26e7b5f56e18207db896f9e30ff956.png](https://i-blog.csdnimg.cn/blog_migrate/2077fddfb30ce5526c7250bc470e87d2.png)
2.出队列操作: 判断当输出栈为空时,先把输入栈的数据依次弹出并加入到输出栈中
![6813c103fff220db0d27a6f2edf35c40.png](https://i-blog.csdnimg.cn/blog_migrate/6faa457866007293bf3fca14f37b4202.png)
![b6353d78e349a26b94fb84e3cba9f2ca.png](https://i-blog.csdnimg.cn/blog_migrate/f101806e44409db5723cf5a16e943165.png)
对输出栈栈顶进行出栈操作,即可完成出队列功能
![1b29c96ad07815993146f9f9f4b6c1f3.png](https://i-blog.csdnimg.cn/blog_migrate/c3fd7de95fc2ec84ab37248d907cdede.png)
具体代码
import
用队列实现栈
这里同样有两个功能需要我们实现,分别是入栈功能和出栈功能
入栈功能
我们可以用入栈操作模拟实现
![fe75f984753d83f2964559afa73b8a5f.png](https://i-blog.csdnimg.cn/blog_migrate/fbe30aa6b4c075901bc85ecb7fa30b42.png)
出栈功能
我们又来到了关键功能,这时候你能猜到,我们又需要用到两个队列去实现这个出栈功能了
但问题在于,我们还能否通过讲数据从一个队列“倒”到另一个队列的方式逆转数据方向呢? 这是不行的,因为队列先入先出的特性,导致分割后队列的出入方向仍然是不变的。所以我们要换个思路:
一个元素入队列了,我们接下来希望这个队列像栈一样通过pop把它直接弹出来,但是前面还有很多个元素排着队呢,这时我们想,只要把前面排队的所有元素先出列到另外一个辅助队列里面去,接下来不就可以直接把这个元素踢出队列从而模拟出栈了吗?
![29c1c5e439676ecce7713766175ef77a.png](https://i-blog.csdnimg.cn/blog_migrate/93ef306f7a7ab43c1df27adf3fc10819.png)
![220c234c15519bf68e843dbbc992c4b8.png](https://i-blog.csdnimg.cn/blog_migrate/2826a10d142b145d1191458eb278631b.png)
当然完成pop操作后我们还要做一件事情,就是辅助队列和主队列互换,以让未来还能按同样的流程再来一次。
![20e4ec5c75d4a51a6388e1347ec1390e.png](https://i-blog.csdnimg.cn/blog_migrate/410dc1f68a52036d42af78c3a48a1f59.png)
具体代码
import
循环队列的实现
设计循环队列的原因
对于普通的单向队列,在入队列和出队列的时候可能会遇到一种“队列假满”的现象,导致空间的浪费如下图所示
![bce6ef24c6e88d9a2ce4164106620cd7.png](https://i-blog.csdnimg.cn/blog_migrate/7804c4b908cf2fc17318c4e12077cbed.png)
所以我们要做的,就是通过设置头部(front)和尾部(rear)两个指针来区分队列的“满的部分”和“空的部分”,并且允许在填充到数组末尾的时候,能通过回到数组的头部这种循环的方式继续填充数组,从而提高数组空间的利用率。
![74ea7a45790b940ccd0d9b05b5db0d97.png](https://i-blog.csdnimg.cn/blog_migrate/a9d391ecc3f9c617143a3d8128870e22.png)
怎么实现从尾部到头部的循环呢? 我们可以通过取余运算符实现,因为当 i = 数组长度- 1的时候,(i + 1) % 数组长度 = 0,也就是说这个时候指针又从尾部回到了数组的头部
![4cbc832029f917a75806f5c0c0fcfd74.png](https://i-blog.csdnimg.cn/blog_migrate/2f4f880512f296bd16e51ec24fd322a1.png)
具体代码
class