《C语言数据结构》严蔚敏,吴伟民版。
上章内容链接:https://blog.youkuaiyun.com/daqino1/article/details/88832307
下章内容链接:https://blog.youkuaiyun.com/daqino1/article/details/88836147
以下内容为队列
队列(queue):是一种先进先出(first in first out, 缩写FIFO)的线性表。只允许在表的一段插入,另一段进行删除。
队尾(rear):允许插入的一端。
对头(front):允许删除的一端。
双端队列(deque):可以像栈一样。也可以一端删除,另一端允许插入和删除。反之也可。
//-----------------队列的抽象化定义-------------------
ADT Queue {
// 构造一个空队列Q
InitQueue(&Q);
// 队列Q被销毁,不再存在
DestroyQueue(&Q);
// 将Q清为空队列
ClearQueue(&Q);
// 若Q为空队列,则返回TRUE,否则FALSE
QueueEmpty(Q);
// 返回Q的元素个数,即队列的长度
QueueLength(Q);
// 用e返回Q的队头元素
GetHead(Q, &e);
// 插入元素e为Q的新的队尾元素
EnQueue(&Q, e);
// 删除Q的队头元素, 并用e返回其值
DeQueue(&Q, &e);
/* 从队头到队尾,依次对Q的每个数据元素调用函数visit()。一旦visit()失败,则操作失败。*/
QueueTraverse(Q, visit());
}
队列也有两种存储表示:
1.链队列:用链表表示的队列。
2.循环队列:用一组地址连续的存储单元一次存放从队列头到队列尾的元素,并且附设两个指针front和rear,分别表示队列头元素和队列尾元素。
//------单链队列-------队列的链式存储结构---------------------
typedef struct QNode {
QElemType data;
struct QNode *next;
} QNode, *QueuePtr;
typedef struct {
QueuePtr front;
QueurPtr rear;
}LinkQueue;
//---------------------基本操作的函数原型说明-----------------
// 构造一个空队列Q
Status InitQueue(LinkQueue &Q);
// 队列Q被销毁,不再存在
Status DestroyQueue(LinkQueue &Q);
// 将Q清为空队列
Status ClearQueue(LinkQueue &Q);
// 若Q为空队列,则返回TRUE,否则FALSE
Status QueueEmpty(LinkQueue Q);
// 返回Q的元素个数,即队列的长度
int QueueLength(LinkQueue Q);
// 用e返回Q的队头元素
Status GetHead(LinkQueue Q, QElemType &e);
// 插入元素e为Q的新的队尾元素
Status EnQueue(LinkQueue &Q, QElemType e);
// 删除Q的队头元素, 并用e返回其值
Status DeQueue(LinkQueue &Q, QElemType &e);
/* 从队头到队尾,依次对Q的每个数据元素调用函数visit()。一旦visit()失败,则操作失败。*/
Status QueueTraverse(LinkQueue Q, visit());
//--------------------基本操作的部分算法描述-------------------
Status InitQueue(LinkQueue &Q) {
// 构造一个空队列Q
Q.front = Q.rear = (QueuePtr)malloc(QNode);
if (!Q.front) {
// 存储分配失败
exit(OVERFLOW);
}
Q.front->next = NULL
return OK;
}
Status DestroyQueue(LinkQueue &Q) {
// 队列Q被销毁,不再存在
while (Q.front) {
Q.rear = Q.front->next;
free(Q.front);
Q.front = Q.rear;
}
return 0;
}
Status EnQueue(LinkQueue &Q, QElemType e) {
// 插入元素e为Q的新的队尾元素
p = (QueuePtr)malloc(sizeof(QNode));
if (!p) {
// 存储分配失败
exit(OVERFLOW);
}
p->data = e;
p->next = NULL
Q.rear->next = p;
Q.rear = p;
return OK;
}
Status DeQueue(LinkQueue &Q, QElemType &e) {
// 删除Q的队头元素, 并用e返回其值
if (Q.front == Q.rear) {
return ERROR;
}
p = Q.front->next;
e = p->data;
Q.front->next = p->next;
if (Q.rear == p) {
Q.rear = Q.front;
}
free(p);
return 0;
}
循环队列的模块说明如下:
//--------------------循环队列------------队列的顺序存储结构-----------------------------------
#define MAXQSIZE 100 // 最大队列长度
typedef struct {
QElemType *base; // 初始化的动态分配存储空间
int front; // 头指针,若队列不空,指向队列头元素
int rear; // 尾指针,若队列不空,指向队列尾元素的下一个位置
}SqQueue;
//-------------------------------------循环队列的基本操作的算法描述----------------------------
Status InitQueue(SqQueue &Q) {
// 构造一个空队列Q
Q.base = (ElemType *)malloc(MAXQSIZE * sizeof(ElemType));
if (!Q.base) {
// 分配存储失败
exit(OVERFLOW);
}
Q.front = Q.rear = 0;
return OK;
}
int QueueLength(SqQueue Q) {
// 返回Q的元素个数,即队列的长度
return (Q.rear-Q.front+MAXQSIZE) % MAXQSIZE;
}
Status EnQueue(SqQueue &Q, QElemType e) {
// 插入元素e为Q的新的队尾元素
if ((Q.rear+1)%MAXQSIZE == Q.front) {
// 队列满
return ERROR;
}
Q.base[Q.rear] = e;
Q.rear = (Q.rear + 1) % MAXQSIZE;
return OK;
}
Status DeQueue(SqQueue &Q, QElemType &e) {
// 若队列不空,则删除Q的队头元素,用e返回其值,并返回OK,否则返回ERROR
if (Q.front == Q.rear) {
return ERROR;
}
e = Q.base[Q.front];
Q.front = (Q.front + 1) % MAXQSIZE;
return OK;
}
队列应用: 处理离散事件,例如:银行排队
上章内容链接:https://blog.youkuaiyun.com/daqino1/article/details/88832307
下章内容链接:https://blog.youkuaiyun.com/daqino1/article/details/88836147