若用戶無法估計所用隊列的長度,則宜采用鏈隊列
鏈式隊列表示:如圖
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; }