什么是队列
栈中元素只能栈顶出入,它是一种特殊的线性表,同样的,队列(Queue)也是一种特殊的线性表。
秉承先来后到的原则,队列中的元素只能从队尾进入,只能从队首出去,也就是说,入队顺序为1、2、3、4,那么出队顺序也一定是1、2、3、4,所以队列是一种先进先出(FIFO,First In, First Out)的数据结构。
顺序表队列
想要实现队列也是很简单的,也可以通过两种线性表来实现,我们先来看看使用顺序表如何实现队列,假设一开始的时候队列中有0个元素,队首和队尾一般都初始都是-1这个位置:

此时有新的元素入队了,队尾向后移动一格(+1),然后在所指向位置插入新的元素:

之后都是同样的方式进行插入,队尾会一直向后移动:

现在我们想要执行出队操作了,那么需要将队首向后移动一格,然后删除队首指向的元素:

这样设计看起来很不错,但是队列是一次性的,最终会被用完,延长数组终究不是办法,所以我们队列上一般会使用循环队列

开始编写代码:
1 | typedef int E; |
初始化代码:
1 | _Bool initQueue(ArrayQueue queue){ |
入队操作
1 | _Bool offerQueue(ArrayQueue queue, E element){ |
出队操作
1 | _Bool isEmpty(ArrayQueue queue){ //在出队之前需要先看看容量是否足够 |
这里我们要记住,我们给的循环队列的大小看似是10,但我们写的这个代码会导致队头也就是front指着的空间始终是空的,他只是出队front+1的元素,与上方参考图有所不同
单链队列
同样的,队列也可以使用链表来实现,并且使用链表的话就不需要关心容量之类的问题了,会更加灵活一些:

当有新的元素入队时,只需要拼在队尾就行了,同时队尾指针也要后移一位:

出队时,只需要移除队首指向的下一个元素即可:

那么我们来编写代码:
1 | typedef int E; |
接着是初始化,初始化的时候,需要把头结点先创建出来:
1 | _Bool initQueue(LinkedQueue queue){ |
入队操作
首先是入队操作,入队其实直接在后面插入新的结点就行了:
1 | _Bool offerQueue(LinkedQueue queue, E element){ |
出队操作
接着是出队操作,出队操作要相对麻烦一点:
1 | E pollQueue(LinkedQueue queue){ |
效果和前面的顺序表实现是一样的,只不过使用链表会更加灵活一些。
说些什么吧!