队列的链式存储结构及实现
生活随笔
收集整理的這篇文章主要介紹了
队列的链式存储结构及实现
小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
隊列的鏈式存儲結構,其實就是線性表的單鏈表,只不過它只是尾進頭出而已,我們把它簡稱為鏈隊列。為了操作上的方便,我們將隊頭指針指向鏈隊列的頭結點,而隊尾指針指向終端節點。如果
空隊列時,front和rear都指向頭結點。
入隊操作:
在隊尾添加元素,先將隊尾元素的next指向添加的元素,然后將隊尾指針重新指向新的隊尾即可。
出隊操作:
頭結結點指向的結點即為隊頭結點,出隊操作,就是把隊頭結點干掉,先把頭結點指向新的隊頭結點(也就是舊的隊頭結點的后繼結點),然后釋放舊的隊頭結點。 如果鏈表除頭結點外只剩一個元素時,則需將rear指向頭結點即可。
下面是隊列鏈式存儲結構實現的具體代碼:
#define _CRT_SECURE_NO_WARNINGS #include <stdio.h> #include <string.h> #include <math.h> #include <stdlib.h> #define QUEUESIZE 10 #define ERROR 0 #define OK 1 #define TRUE 1 #define FALSE 0 #define EleType int #define Status int //鏈隊列結點 typedef struct QueueNode {EleType e;//數據域struct QueueNode* next;//指針域 }QueueNode,*LinkQueuePoi; typedef struct LinkQueue {LinkQueuePoi front;//指向頭結點LinkQueuePoi rear;//指向隊尾 }LinkQueue; /* 初始化鏈隊列 鏈隊列為空時,鏈隊列隊頭指針隊尾指針均指向頭結點 */ Status InitLinkQueue(LinkQueue* queue) {//空指針if (!queue){return ERROR;}QueueNode* node = (QueueNode*)malloc(sizeof(QueueNode));//頭結點node->next = NULL;queue->front = queue->rear = node;return OK; } /* 清空鏈隊列 將所有元素釋放 */ Status CleaerLinkQueue(LinkQueue* queue) {//空指針if (!queue){return ERROR;}//空鏈隊列if (queue->front == queue->rear){return ERROR;}QueueNode* node = queue->front->next;//隊頭元素while (node){queue->front->next = node->next;//指向新的隊頭結點if (queue->rear == node)//當刪除的是隊尾元素時,將隊尾指針指向頭結點{queue->rear = queue->front;}free(node);//釋放舊的隊頭結點node = queue->front->next;}return OK; } /* 判斷鏈隊列是否為空隊列 */ Status EmptyLinkQueue(LinkQueue* queue) {//空指針if (!queue){return ERROR;}//空鏈隊列if (queue->front == queue->rear){return TRUE;}return FALSE; } /* 獲取鏈隊列長度 */ int LengthLinkQueue(LinkQueue* queue) {//空指針if (!queue){return ERROR;}//空鏈隊列if (queue->front == queue->rear){return 0;}QueueNode* node = queue->front->next;int num = 0;while (node){node = node->next;num++;}return num; } /* 在鏈隊列隊尾添加元素 先將新元素添加到鏈表尾部,然后將隊列尾指針指向這個新元素 */ Status AddQueue(LinkQueue* queue,EleType e) {//空指針if (!queue){return ERROR;}QueueNode* node = (QueueNode*)malloc(sizeof(QueueNode));if (!node){return ERROR;}node->next = NULL;node->e = e;queue->rear->next = node;//將新結點添加到鏈表表中queue->rear = node;//隊尾指針指向新的隊尾結點return OK; } /* 從鏈隊列中刪除隊頭元素 先將頭結結點指向新的隊頭結點,然后釋放原來的隊頭結點 */ Status DelQueue(LinkQueue* queue, EleType *e) {//空指針if (!queue){return ERROR;}//注意queue->front是頭結點,頭結點指向的結點才是隊頭結點QueueNode* node = queue->front->next;//舊隊頭結點*e = node->e;queue->front->next = node->next;//隊頭指針指向新的隊頭結點//當刪除的是隊尾元素時,將隊尾指針指向頭結點if (node = queue->rear){queue->rear = queue->front;}return OK; } /* 打印鏈隊列元素 */ void PrintfLinkQueue(LinkQueue* queue) {if (!queue){return;}QueueNode* node = queue->front->next;while (node){printf("%d,", node->e);node = node->next;}printf("\n");return; } int main(int argc, char *argv[]) {LinkQueue queue;InitLinkQueue(&queue);AddQueue(&queue, 1);AddQueue(&queue, 2);AddQueue(&queue, 3);AddQueue(&queue, 4);AddQueue(&queue, 5);AddQueue(&queue, 6);AddQueue(&queue, 7);AddQueue(&queue, 8);AddQueue(&queue, 9);printf("鏈隊列元素個數:%d\n",LengthLinkQueue(&queue));printf("展示元素:\n");PrintfLinkQueue(&queue);int e1, e2;DelQueue(&queue, &e1);DelQueue(&queue, &e2);printf("刪除元素:%d,%d\n", e1, e2);printf("展示元素:\n");PrintfLinkQueue(&queue);printf("鏈隊列元素個數:%d\n", LengthLinkQueue(&queue));CleaerLinkQueue(&queue);printf("清空元素后,長度為%d,rear = %p,front=%p",LengthLinkQueue(&queue), queue.rear,queue.front);printf("\n");return 0; } 驗證結果截圖:
對于循環隊列與鏈隊列的比較,可以從時間和空間2方面來考慮,從時間上,他們的基本操作都是常數時間,即都為O(1),不過循環隊列是事先申請好空間,使用期間不釋放,而對于鏈隊列,每次申請和釋放結點也會存在一些時間開銷,如果入隊出隊頻繁,則2者還是有些細微的差異。對于空間方面來說,循環隊列必須有一個固定的長度,所以就有了存儲元素個數和空間浪費的問題。而鏈隊列就不存在這個問題,盡管它需要一些指針域,會產生一些空間上的開銷,但也可以接受。所以在空間上,鏈隊列更加靈活。
總結
以上是生活随笔為你收集整理的队列的链式存储结构及实现的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: Django多表查询练习题
- 下一篇: 查找-------(HashCode)哈