数据结构:单链队列
文章目錄
- 隊(duì)列:
- 單鏈隊(duì)列的實(shí)現(xiàn)及操作:
- 1.定義一個隊(duì)列
- 2.構(gòu)造一個空隊(duì)列
- 3.銷毀隊(duì)列
- 4.插入元素e到隊(duì)尾
- 5.刪除隊(duì)頭元素,用e返回其值
- 單鏈隊(duì)列操作實(shí)例及代碼:
隊(duì)列:
隊(duì)列是先進(jìn)先出的線性表。
隊(duì)列只允許在表的一端插入元素,在另一端刪除元素。
隊(duì)列中允許插入的一端叫隊(duì)尾,允許刪除的一端叫隊(duì)頭。
單鏈隊(duì)列的實(shí)現(xiàn)及操作:
1.定義一個隊(duì)列
一個鏈隊(duì)列,由每個結(jié)點(diǎn)連接起來。由于插入和刪除是在隊(duì)頭和隊(duì)尾進(jìn)行的,我們?yōu)榱朔奖闫鹨?#xff0c;直接弄兩個指針,指向頭結(jié)點(diǎn)和隊(duì)尾元素所在結(jié)點(diǎn)。
typedef struct QNode {QElemType_L data;struct QNode *next; }QNode; typedef QNode* QueuePtr; typedef struct {QueuePtr front; QueuePtr rear; }LinkQueue;2.構(gòu)造一個空隊(duì)列
我們增加一個頭結(jié)點(diǎn),首先分配一個頭結(jié)點(diǎn)的內(nèi)存空間。當(dāng)隊(duì)列為空時,隊(duì)頭指針和隊(duì)尾指針都指向頭結(jié)點(diǎn),而且頭結(jié)點(diǎn)的指針域的指針指向空,意味著隊(duì)列里面沒有存元素。
Status InitQueue_L(LinkQueue &Q) {Q.front = Q.rear = (QueuePtr)malloc(sizeof(QNode));if(!Q.front)exit(OVERFLOW);Q.front->next = NULL;return OK; }3.銷毀隊(duì)列
這個銷毀最終把頭結(jié)點(diǎn)也給銷毀了。
注意一點(diǎn),鏈表知道頭指針,就能根據(jù)->next確定后面所有結(jié)點(diǎn),我們初始化增加了一個尾指針,讓他指向最后一個結(jié)點(diǎn),但這并不意味著我們改變了尾指針指向的位置,鏈表中間的結(jié)點(diǎn)就沒了,中間的結(jié)點(diǎn)還是可以根據(jù)頭指針和->next找到的,我們其實(shí)可以把尾指針理解成一個標(biāo)記,他的位置并不影響鏈表,只不過方便了我們找隊(duì)尾元素所在結(jié)點(diǎn)。真正影響鏈表的是我們的頭指針,我們遍歷也是通過頭指針->next來的,每個結(jié)點(diǎn)都會用到。
這里我們就把尾指針當(dāng)作一個轉(zhuǎn)移變量來用了。先存頭結(jié)點(diǎn)指向的下一個結(jié)點(diǎn)的位置,然后把頭結(jié)點(diǎn)的位置free掉,再讓頭結(jié)點(diǎn)指向尾指針指向的位置,即將下一個結(jié)點(diǎn)的位置當(dāng)作頭結(jié)點(diǎn)。一路循環(huán),當(dāng)沒有下一個存元素的結(jié)點(diǎn)了,頭指針的位置指向頭結(jié)點(diǎn),尾指針被賦為null,頭指針free之后頭結(jié)點(diǎn)的空間也沒了,然后把頭指針也賦為null。最終頭指針尾指針都指向null,而且所有空間全被free掉。
void DestroyQueue_L(LinkQueue &Q) {while(Q.front){Q.rear = Q.front->next;free(Q.front);Q.front = Q.rear; } }如果是清空的話,有一點(diǎn)不同,就是還有頭結(jié)點(diǎn),只不過->next指向null了,和初始狀態(tài)一樣,頭指針,尾指針指向頭結(jié)點(diǎn),頭結(jié)點(diǎn)指向下一個結(jié)點(diǎn)的指針指向null。這里還是把尾指針當(dāng)作一個轉(zhuǎn)移變量,初始指向第一個結(jié)點(diǎn),每次讓頭指針指向的下一個結(jié)點(diǎn)變成尾指針這個轉(zhuǎn)移變量指向的下一個結(jié)點(diǎn),然后free掉尾指針原來指向的結(jié)點(diǎn),然后把當(dāng)前尾指針指向的結(jié)點(diǎn)更新為尾指針這個轉(zhuǎn)移變量指向的下一個結(jié)點(diǎn)。舉個例子即可明白。
void ClearQueue_L(LinkQueue &Q) {Q.rear = Q.front->next;while(Q.rear){Q.front->next = Q.rear->next; free(Q.rear); Q.rear = Q.front->next;}Q.rear = Q.front; }4.插入元素e到隊(duì)尾
插入元素,分配一個結(jié)點(diǎn)的空間,然后原尾指針的下一個位置指向新結(jié)點(diǎn),更新尾指針。
Status EnQueue_L(LinkQueue &Q, QElemType_L e) {QueuePtr p;p = (QueuePtr)malloc(sizeof(QNode));if(!p)exit(OVERFLOW);p->data = e;p->next = NULL;Q.rear->next = p;Q.rear=p;return OK; }5.刪除隊(duì)頭元素,用e返回其值
刪除先判端是否有元素,然后取出隊(duì)頭元素,讓頭結(jié)點(diǎn)指針域里面的指針指向的下一個結(jié)點(diǎn)變成第一個元素的結(jié)點(diǎn)指向的下一個元素的結(jié)點(diǎn)。
這里我們還要考慮是否對尾指針產(chǎn)生影響,當(dāng)僅有一個元素時,刪除后隊(duì)列為空,尾指針應(yīng)該指向頭結(jié)點(diǎn)。
最后把刪除的結(jié)點(diǎn)的空間釋放掉即可。
Status DeQueue_L(LinkQueue &Q, QElemType_L &e) {QueuePtr p;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 OK; }單鏈隊(duì)列操作實(shí)例及代碼:
代碼:
#include<cstdio> #include<cstdlib>#define OK 1 #define ERROR 0 #define OVERFLOW -2 #define UNDERFLOW -3 #define TRUE 1 #define FALSE 0typedef int QElemType_L; typedef int Status;typedef struct QNode {QElemType_L data;struct QNode *next; }QNode; typedef QNode* QueuePtr; typedef struct {QueuePtr front; QueuePtr rear; }LinkQueue; Status InitQueue_L(LinkQueue &Q) {Q.front = Q.rear = (QueuePtr)malloc(sizeof(QNode));if(!Q.front)exit(OVERFLOW);Q.front->next = NULL;return OK; } void ClearQueue_L(LinkQueue &Q) {Q.rear = Q.front->next;while(Q.rear){Q.front->next = Q.rear->next; free(Q.rear); Q.rear = Q.front->next;}Q.rear = Q.front; } void DestroyQueue_L(LinkQueue &Q) {while(Q.front){Q.rear = Q.front->next;free(Q.front);Q.front = Q.rear; } } Status EnQueue_L(LinkQueue &Q, QElemType_L e) {QueuePtr p;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_L(LinkQueue &Q, QElemType_L &e) {QueuePtr p;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 OK; } void QueueTraverse_L(LinkQueue Q, void (Visit)(QElemType_L)) {QueuePtr p;p = Q.front->next;while(p){Visit(p->data);p = p->next;}printf("\n"); } void PrintElem(QElemType_L e) {printf("%d ", e); } Status QueueEmpty_L(LinkQueue Q) {if(Q.front==Q.rear)return TRUE;elsereturn FALSE; } int main(){LinkQueue Q;int i;QElemType_L e;printf("初始化鏈隊(duì) Q ...\n"); InitQueue_L(Q);printf("\n");QueueEmpty_L(Q) ? printf(" Q 為空!!\n") : printf(" Q 不為空!\n");printf("\n");for(i=1; i<=6; i++) {printf("元素 \"%2d\" 入隊(duì),", 2*i);EnQueue_L(Q, 2*i);printf("\n");}printf("\n");printf(" Q 中的元素為:Q = "); QueueTraverse_L(Q, PrintElem);printf("\n");DeQueue_L(Q, e);printf("隊(duì)頭元素 \"%d\" 出隊(duì)...\n", e);printf(" Q 中的元素為:Q = "); QueueTraverse_L(Q, PrintElem);printf("\n"); printf("銷毀 Q 前:");Q.front!=NULL && Q.rear!=NULL ? printf(" Q 存在!\n") : printf(" Q 不存在!!\n");DestroyQueue_L(Q);printf("銷毀 Q 后:");Q.front!=NULL && Q.rear!=NULL ? printf(" Q 存在!\n") : printf(" Q 不存在!!\n");printf("\n"); }輸出:
初始化鏈隊(duì) Q …
Q 為空!!
元素 " 2" 入隊(duì),
元素 " 4" 入隊(duì),
元素 " 6" 入隊(duì),
元素 " 8" 入隊(duì),
元素 “10” 入隊(duì),
元素 “12” 入隊(duì),
Q 中的元素為:Q = 2 4 6 8 10 12
隊(duì)頭元素 “2” 出隊(duì)…
Q 中的元素為:Q = 4 6 8 10 12
銷毀 Q 前: Q 存在!
銷毀 Q 后: Q 不存在!!
總結(jié)
- 上一篇: linux系统如何挂载新硬盘,Linux
- 下一篇: (数论1)质因数