1、介紹算法
隊列(Queue),計算機中一種經常使用的數據結構,具備先進先出FIFO的特色。數組
通俗一點,就跟生活中超市購物結帳排隊同樣,靠前的結帳先走,新來的排在後面等待。數據結構
對於隊列中的元素,通常都在隊頭出隊,在隊尾入隊,隊頭用Q.front表示,隊尾用Q.rear表示。函數
隊列的實現有兩種方式,經過數組或者鏈表實現。基於數組實現的隊列通常稱做順序隊列,基於鏈表實現的隊列通常稱做鏈式隊列。測試
鏈式隊列中,有兩個指針,分別是隊頭指針和隊尾指針。爲了操做方便,能夠給鏈隊列添加一個頭結點,並令頭指針指向頭結點。ui
空隊列判決條件:頭指針和尾指針均指向頭結點。也即Q.front == Q.rear。 spa
本文采用鏈表實現隊列,鏈隊列的操做即爲單鏈表的插入和刪除的特殊狀況,只是尚需修改尾指針或頭指針。debug
2、示圖指針
3、算法code
#define QUEUE_OVERFLOW -1 #define OK 1 #define ERROR 0 #define TRUE 1 #define FALSE 0 typedef int QElemType; typedef int Status; /// ----- 單鏈隊列 ------- 隊列的鏈式存儲結構 typedef struct QNode { QElemType data; struct QNode *next; }QNode, *QueuePtr; typedef struct { QueuePtr front; //隊頭指針 QueuePtr rear; //隊尾指針 }LinkQueue; /// --- 基本操做的函數原型說明 ----- Status InitQueue(LinkQueue &Q); //構造一個空的隊列Q Status DestroyQueue(LinkQueue &Q); //銷燬隊列Q,Q再也不存在 Status ClearQueue(LinkQueue &Q); //將隊列Q清空 Status QueueEmpty(LinkQueue Q); //判斷隊列Q是否爲空,若空,返回TURE, 不然,返回FALSE int QueueLength(LinkQueue Q); //返回Q的元素個數,也即隊列的長度 Status GetHead(LinkQueue Q, QElemType &e); //若隊列Q不爲空,則用e返回Q的隊頭元素,並返回OK;不然,返回ERROR Status EnQueue(LinkQueue &Q, QElemType e); //插入元素e爲Q的新的隊尾元素 Status DeQueue(LinkQueue &Q, QElemType &e); //若隊列不空,則刪除Q的隊頭元素,用e返回其值,並返回OK,不然,返回ERROR void QueueVisit(LinkQueue &Q); //訪問隊列元素
4、代碼
Status InitQueue(LinkQueue &Q) { //構造一個空隊列Q Q.front = Q.rear = (QueuePtr)malloc(sizeof(QNode)); if (!Q.front) exit(QUEUE_OVERFLOW); //存儲分配失敗 Q.front->next = NULL; return OK; } Status DestroyQueue(LinkQueue &Q){ //銷燬隊列Q while (Q.front){ Q.rear = Q.front->next; free(Q.front); //從隊頭取出每個元素並釋放內存,Q.rear做爲一個臨時指針使用 Q.front = Q.rear; } cout<<"隊列已銷燬"<<endl; return OK; } Status ClearQueue(LinkQueue &Q){ //清空隊列Q Q.rear = Q.front; cout<<"隊列已清空"<<endl; return OK; } Status QueueEmpty(LinkQueue Q){ //判斷隊列Q是否爲空 if (Q.front == Q.rear) { cout<<"隊列爲空"<<endl; return TRUE; } cout<<"隊列不爲空"<<endl; return FALSE; } int QueueLength(LinkQueue Q){ //獲取隊列的長度 QNode *p = Q.front->next; int len = 0; while (p){ len++; p = p->next; } cout<<"隊列長度:"<<len<<endl; return len; } Status GetHead(LinkQueue Q, QElemType &e){ //獲取隊頭元素 if (Q.front == Q.rear) { return FALSE; } QNode *p = Q.front->next; e = p->data; cout<<"隊頭元素:"<<e<<endl; return OK; } Status EnQueue(LinkQueue &Q, QElemType e){ //插入元素e爲Q的新的隊尾元素 QNode *p = (QueuePtr)malloc(sizeof(QNode)); if (!p) exit(QUEUE_OVERFLOW); p->data = e; p->next = NULL; Q.rear->next = p;//當前隊尾指針的next指針指向新元素 Q.rear = p;//修改隊尾指針 cout<<"入隊:"<<e<<endl; return OK; } Status DeQueue(LinkQueue &Q, QElemType &e){ //刪除隊頭元素 if (Q.front == Q.rear) return ERROR; QNode *p = Q.front->next; e = p->data; Q.front->next = p->next; cout<<"出隊:"<<e<<endl; if (Q.rear == p) { Q.rear = Q.front; } free(p); return OK; } void QueueVisit(LinkQueue &Q){ if (Q.front == Q.rear){ cout<<"隊列爲空"<<endl; return; } //訪問隊列元素 QNode *p = Q.front->next; printf("隊列順序爲:"); while (p){ QElemType e = p->data; p = p->next; printf("%d ",e); } cout<<endl; }
5、測試
int main() { //構造隊列 LinkQueue queue; if (InitQueue(queue) == OK){ for (int i = 1; i <= 10; ++i) { EnQueue(queue,i);//入隊列 } } //判斷隊列是否爲空 QueueEmpty(queue); //訪問隊列元素 QueueVisit(queue); //獲取隊列長度 QueueLength(queue); //獲取隊頭元素 QElemType e; GetHead(queue, e); //出隊列 for (int i=1; i<5 ; i++) { DeQueue(queue, e); } QueueVisit(queue); //清空隊列 ClearQueue(queue); QueueEmpty(queue); //銷燬隊列 DestroyQueue(queue); return 0; }
6、打印
/Users/xiayuanquan/CLionProjects/queueTest/cmake-build-debug/queueTest 入隊:1 入隊:2 入隊:3 入隊:4 入隊:5 入隊:6 入隊:7 入隊:8 入隊:9 入隊:10 隊列不爲空 隊列順序爲:1 2 3 4 5 6 7 8 9 10 隊列長度:10 隊頭元素:1 出隊:1 出隊:2 出隊:3 出隊:4 隊列順序爲:5 6 7 8 9 10 隊列已清空 隊列爲空 隊列已銷燬 進程已結束,退出代碼 0