若用户无法估计所用队列的长度,则宜采用链队列
链式队列表示:如图
Q.front 指向头结点
Q.rear 指向尾结点
链队列的类型定义:
#define MAXQSIZE 100 //最大队列长度 typedef struct Qnode{ // 数据域 QElemType data; // 指针域 // 栈是stack,所以是SNode // 队列是 Queue,所以是QNode // 所指向结点仍然是 Qnode 这种类型 stuct Qnode *next; }QNode, *QuenPtr;
typedef struct{ // 队头指针 QueuePtr front; // 队尾指针 QueuePtr rear; // 链式队列 } LinkQueue;
链队列运算指针的变化状况
① 空队列时,头指针尾指针都指向一个结点,如图:
② 元素 x 入队列,Q.rear 只能指向队尾
再有元素入队,如下图
③ 要出队时,只能出 x ,不能直接出 y
------------------------------------------------------------------------------------------------------------------------------------------------
链队列的操作——链队列初始化
直接在内存当中找到一个头结点,然后首尾指针都指向头结点
#define MAXQSIZE 100 //最大队列长度 typedef struct Qnode{ // 数据域 QElemType data; // 指针域 // 栈是stack,所以是SNode // 队列是 Queue,所以是QNode // 所指向结点仍然是 Qnode 这种类型 stuct Qnode *next; }QNode, *QuenPtr; typedef struct{ // 队头指针 QueuePtr front; // 队尾指针 QueuePtr rear; // 链式队列 } LinkQueue; Status InitQueue(LinkQueue &Q){ Q.front = Q.rear = (QueuePtr)malloc(sizeof(QNode)); // 加一个内存溢出判断,防止出问题 if(!Q.front){ exit(OVERFLOW); } // next 域置空 Q.front->next = NULL; }
链队列的操作——销毁栈队列
销毁栈队列就是从队头结点开始,依次释放所有结点
Status DestroyQueue(LinkQueue &Q){ while(Q.front){ p = Q.front -> next; free(Q.front); Q.front = p;
return OK; } }
或者使用如下代码:
Status DestroyQueue(LinkQueue &Q){ Q.rear = Q.front -> next; free(Q.front); Q.front = Q.rear; return OK; }
链队列的操作——将元素 e 入队
链队列入队,只能在队尾入,也就是从 an 后入队
#define MAXQSIZE 100 //最大队列长度 typedef struct Qnode{ // 数据域 QElemType data; // 指针域 // 栈是stack,所以是SNode // 队列是 Queue,所以是QNode // 所指向结点仍然是 Qnode 这种类型 stuct Qnode *next; }QNode, *QuenPtr; typedef struct{ // 队头指针 QueuePtr front; // 队尾指针 QueuePtr rear; // 链式队列 } LinkQueue; Status EnQueue(LinkQueue &Q, QElemType e){ // 开辟一个内存空间 p = (QueuePtr)malloc(sizeof(QNode)); // 如果分配不成功,则直接退出 if(!p){ exit(OVERFLOW); } // 将 e 存入 p所指结点 的数据域,且将 P所指结点 p -> data = e; p -> next = NULL; // 尾指针所指结点的指针域修改,使其接上新添加的结点 Q.rear -> next = p; // 修改尾指针所指向结点 Q.rear = p; return OK; }
链队列的操作——链队列出队
链队列的出队是从队头出队的,因此要删掉头结点后面的那个结点
直接修改前驱的指针域,就可以完成。最后再释放掉
① new 一个指针p,使 指针p 指向头结点后边那个结点
p = Q.fornt -> next;
② 修改 Q.front -> next ,使其原本指向出队结点的指针域指向出队结点后边那个结点
Q.front -> next = p -> next;
③ 释放掉指针P
用 C++ 就是 delete p;
用 C 就是 free(p);
④ 假如需要知道出队的元素是啥,就让 e 存放并返回:
e = p -> data;
具体代码如下:
#define MAXQSIZE 100 //最大队列长度 typedef struct Qnode{ // 数据域 QElemType data; // 指针域 // 栈是stack,所以是SNode // 队列是 Queue,所以是QNode // 所指向结点仍然是 Qnode 这种类型 stuct Qnode *next; }QNode, *QuenPtr; typedef struct{ // 队头指针 QueuePtr front; // 队尾指针 QueuePtr rear; // 链式队列 } LinkQueue; Status DeQueue(LinkQueue &Q, QElemType &e){ // 判空 if(Q.front == Q.rear){ return ERROR; } p = Q.front -> next; e = p -> data; Q.front -> next = p -> next; // 如果删除后,p 指针向后移动一个,下一个元素正好就是尾结点 // 那么就不仅要修改头结点的指针,也要修改尾指针 if(Q.rear == p){ Q.rear = Q.front; } delete p; return OK; }
链队列的操作——求链队列的队头元素
#define MAXQSIZE 100 //最大队列长度 typedef struct Qnode{ // 数据域 QElemType data; // 指针域 // 栈是stack,所以是SNode // 队列是 Queue,所以是QNode // 所指向结点仍然是 Qnode 这种类型 stuct Qnode *next; }QNode, *QuenPtr; typedef struct{ // 队头指针 QueuePtr front; // 队尾指针 QueuePtr rear; // 链式队列 } LinkQueue; // 求链队列的队头元素 Status GetHead(LinkQueue Q, QElemType &e){ if(Q.front == Q.rear){ return ERRORl; } e = Q.front -> next -> data; return OK; }