佇列的鏈式表示和實現
阿新 • • 發佈:2021-10-10
若使用者無法估計所用佇列的長度,則宜採用鏈佇列
鏈式隊列表示:如圖
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; }