队列

来源:互联网 发布:清歌五笔 mac 编辑:程序博客网 时间:2024/05/29 10:12
1. 队列,是一种数据结构。


2. 队列,是特殊的线性表。规定队列只能从一端插入,另一端删除。插入的一端称为队尾,删除的一端称为队头。也就是说,先进队的数据,先出队,后进的数据后出,即所谓的FIFO。这就是它的特殊之处。


3. 队列有多种实现方式,可以用顺序线性表实现,也可以用链表实现。

3.1 有头有尾的队列
有头有尾的队列,又称为单向队列。单向队列,可以通过数组或单向链表来实现。根据队列的定义,队列元素只能在队尾插入,在队头删除。队列用数组来实现时,数组的长度就是队列的最大容量。用单链表来实现时,链表的头节点就是队列的头,链表的尾节点就是队列的队尾。由于队列必须在队尾、队头两个不同的地方进行插入、删除操作,所以,需要两个不同的指针,分别指向队尾、队头。一般情况下,分别用front、rear指向队头、队尾。

对于front、rear的指向,有两种不同的说法,一是front指向队头的前一个位置,rear指向队尾;一是front指向队头的位置,rear指向队尾待插入数据的位置。

3.1.1 队列的初始化
队列初始化,是建队后的第一步。建队的意思是,如果采用数组实现,则定义一个数组;如果是静态链表实现,则定义一个数组和节点类型;如果是动态链表,则是定义一个链表节点。队列初始化,目的是让front、rear指向队尾的同一个位置,表示队列为空。初始化后,队列为空。

3.1.2 入队
如果有数据入队,则存放在rear所在的位置,然后rear再加1指向下一个待插入的位置。在整个过程中,指向队头的front始终不变。

3.1.3 出队
出队操作,与入队操作完全不同,出队操作在队头front端进行。数据出队后,front指向新的队头,即出队数据的下一个数据位置。在这个过程中队尾rear不变。

3.1.4 判队空
单向队列判断队是否为空,比较简单。前面已经介绍过,front、rear分别指向队头、队尾。因此很容易得知,当front、rear指向同一个位置时,即front==rear时,队列为空。空队列类似于初始化后的队列一样,队头、队尾是同一个位置,也即front、rear指向同一个位置。

3.1.5 判队满
队列空间有限,不能无限地插入数据,所以每次插入前要判断队列是否满了。那么怎么判断呢?

3.2 无头无尾的循环队列

循环队列,是把队头、队尾相连,形成一个逻辑环。循环队列的入队、出队同样需要移动front、rear。当rear指向队列上界时,通过加1操作,翻转指向队头。循环队列同样需要front、rear两个指针指向队头、队尾,这类似于单向队列。

如果有数据入队,则rear顺时针加1。有数据出队时,则front顺时针加1。所以可以看出,front、rear二者是在向同一个方向发展。这样的话,有两种个情况可能使二者指向同一个位置,一是队列空了,front赶上了rear;一是队列满了,rear倒赶上front。

所以这种情况下,我们无法用front==rear来判断队列是空还是满。

解决这个问题有多种方法,选择哪种都行,原则就是能区分队列是满还是空。这里我们采用一个变量来记录队列中元素总数,这种方法比较简单,容易实现。

循环队列,在实际编程中,使用非常频繁,这里我们详细看看它的各种基本操作。这些操作包括队列初始化、入队、出队、判断队列空,以及判断队列满。

假设有如下定义:
#define QueueSize_UartLen 8
typedef struct
{
int front;
int rear;
int counter;
int uart_data[QueueSize_UartLen];
}CIRQUEUE_UART;
这里,front、rear两个成员变量分别指向队头、队尾。counter用来记录队列元素的个数,方便判断队空、队满。int类型的数组uart_data用来存储队列元素,也可以是其它类型的数组。

3.2.1 队列初始化
建队后,首先要对其进行初始化,让front、rear均指向队尾同一个位置,并且让计数器清零。
void InitQueue(CIRQUEUE_UART *queue)
{
queue->front = 0;
queue->rear = 0;
queue->counter = 0;
}
初始化函数的形参,是CIRQUEUE_UART类型的指针变量queue。通过调用InitQueue(),即可对指定的队列进行初始化。

3.2.2 入队
有数据元素需要入队的,首先要潘盾队列是否已经满了。如满,则不能再进行入队操作。
int InQueue(CIRQUEUE_UART *queue, int data)
{
if(QueueFull(queue))
{
//输出队满提示
return 0;
}
else
{
queue->uart_data[queue->rear] = data;
queue->counter++;
queue->rear = (queue->rear+1) % QueueSize_UartLen;
return 1;
}
}























原创粉丝点击