版权声明:转载请附上文章地址https://blog.csdn.net/qq_42672839
1.队列的概念
只允许在一端插入数据操作,在另一端进行删除数据操作的特殊线性表;进行插入操作的一端称为队尾(入队列),进行删除操作的一端称为队头(出队列);队列具有先进先出(FIFO)的特性。
顺序存储就是用数组实现,比如有一个n个元素的队列,数组下标0的一端是队头,入队操作就是通过数组下标一个个顺序追加,不需要移动元素,但是如果删除队头元素,后面的元素就要往前移动,对应的时间复杂度就是O(n),性能自然不高。
2.队列的API
jdk1.5中的阻塞队列的操作如下:
add 增加一个元索 如果队列已满,则抛出一个IIIegaISlabEepeplian异常
remove 移除并返回队列头部的元素 如果队列为空,则抛出一个NoSuchElementException异常
element 返回队列头部的元素 如果队列为空,则抛出一个NoSuchElementException异常
offer 添加一个元素并返回true 如果队列已满,则返回false
poll 移除并返问队列头部的元素 如果队列为空,则返回null
peek 返回队列头部的元素 如果队列为空,则返回null
put 添加一个元素 如果队列满,则阻塞
take 移除并返回队列头部的元素 如果队列为空,则阻塞
3.队列的逻辑
3.1 正常的一个顺序队列:
队列的特性:先进先出,进入队列从左边进入,从右边出队列,所以A先进也是A先出
3.2 循环队列
循环公式 tail=(tail+1)%array.Length;
什么是循环队列呢?就是有两个指针,front指向队头,rear指向对尾元素的下一个位置,元素出队时front往后移动,如果到了对尾则转到头部,同理入队时rear后移,如果到了对尾则转到头部,这样通过下标front出队时,就不需要移动元素了。
队列为空时,front和rear相等,那队列什么时候判断为满呢?按照循环操作rear依次后移,然后再从头开始,也是出现rear和front相等时,队列满。这样跟队列空的情况就相同了,为了区分这种情况,规定数组还有一个空闲单元时,就表示队列已满,因为rear 可能在front后面,也可能循环到front前面,所以队列满的条件就变成了(rear+1)%maxsize = front ,同时队列元素个数的计算就是(rear -front+maxsize)%maxsize。
队列的链式表示和实现(简称为“链队列”)
队列的链式存储是在链表的基础上,按照“先进先出”的原则操作数据元素。
例如,将队列(A,B,C,D,E)依次入队,然后再依次出队。
代码实现:(C语言)
#include <stdio.h>
#include <stdlib.h>
typedef struct QNode
{
int data;
struct QNode *next;
}QNode;
QNode *initQueue()
{
QNode *queue = (QNode*)malloc(sizeof(QNode));
queue->next = NULL;
return queue;
}
QNode *enQueue(QNode *rear, int data)
{
QNode *enElem = (QNode*)malloc(sizeof(QNode));
enElem->data = data;
enElem->next = NULL;
//使用尾插法向链队列中添加数据元素
rear->next = enElem;
rear = enElem;
return rear;
}
void DeQueue(QNode *front, QNode *rear)
{
if (front->next == NULL)
{
printf("队列为空");
return ;
}
QNode *p = front->next;
printf("%s", p->data);
front->next = p->next;
if (rear == p)
{
rear = front;
}
free(p);
}
int main()
{
QNode *queue, *front, *rear;
queue = front = rear = initQueue(); //创建头结点
//向链队列中添加结点,使用尾插法添加的同时,队尾指针需要指向链表的最后一个元素
rear = enQueue(rear, A);
rear = enQueue(rear, B);
rear = enQueue(rear, C);
rear = enQueue(rear, D);
rear = enQueue(rear, E);
//入队完成,所有数据元素开始出队列
DeQueue(front, rear);
DeQueue(front, rear);
DeQueue(front, rear);
DeQueue(front, rear);
DeQueue(front, rear);
DeQueue(front, rear);
return 0;
}
运行结果:
ABCDE队列为空