FIFO 隊列的鏈表和數組實現

FIFO (First-in, First-out,先進先出)隊列:當執行delete操作時刪除那些呆在隊列中時間最長的元素。

FIFO 隊列是這樣一個ADT,包含兩個基本操作:插入(put)一個新的項、刪除(get)一個最早插入的項。

一、FIFO隊列的鏈表實現

FIFO 隊列和下堆棧的區別在於新項的插入是在尾部,而不是在頭部。因此實現程序要保存一個指向鏈表最後一個節點的尾指針tail ,因此當Put操作時,將tail 指針指向的next 指向新節點,然後更新tail指針,讓它指向那個新的節點。

FIFO_LinkList.cpp
[cpp] view plain copy
  1. /************************************************************* 
  2. 功能:先進先出隊列的鏈表形式實現:Init、Put、Get操作 
  3. 說明:  從頭部Get,從尾部Put 
  4. 時間: 2015/02/03 
  5. 作者: quinn 
  6. **************************************************************/  
  7. #include<stdio.h>  
  8. #include<malloc.h>  
  9. #include<stdlib.h>  
  10. typedef int Item;  
  11. typedef struct Node Node;  
  12. typedef Node* Queue;  
  13. struct Node //節點結構  
  14. {  
  15.     Item item;  
  16.     Node* next;  
  17. };  
  18. static int maxN = 10;  
  19. static Queue q = NULL;  
  20. static Node* tail = NULL;  
  21.   
  22. //新建一個節點  
  23. Node* NewNode(Item item, Node* Next) // Next爲插入的後一節點  
  24. {  
  25.     Node* x = (Node*)malloc(sizeof(*x));//被插入的節點  
  26.     x->item = item;  
  27.     x->next = Next;  
  28.     return x;  
  29. }  
  30.   
  31. //隊列初始化  
  32. void QueueInit(int maxN)  
  33. {  
  34.     q =  NULL;  
  35. }  
  36.   
  37. //判斷隊列是否爲空  
  38. int QueueIsEmpty()  
  39. {  
  40.     return (q == NULL);  
  41. }  
  42.   
  43. //put操作  
  44. void QueuePut( Item item)  
  45. {  
  46.     if(QueueIsEmpty())  
  47.     {  
  48.         q = (tail = NewNode(item, q));  
  49.     }  
  50.     else  
  51.     {  
  52.         tail->next = NewNode(item, tail->next);  
  53.         tail = tail->next;  
  54.     }  
  55.     printf("Put: %d\n", item);  
  56. }  
  57.   
  58. //get操作  
  59. Item QueueGet()  
  60. {  
  61.     if(q == NULL)  
  62.     {  
  63.         printf("序列爲空!\n");  
  64.         return -1;  
  65.     }  
  66.   
  67.     Item firstItem = q->item;//序列的頭元素  
  68.     Node* tmpNode = q;  
  69.     q = q->next;  
  70.     free(tmpNode);  
  71.     return firstItem;  
  72. }  
  73.   
  74. //測試程序  
  75. int main()  
  76. {  
  77.     QueueInit(maxN);  
  78.     QueuePut(2);  
  79.     QueuePut(3);  
  80.     QueuePut(4);  
  81.     printf("\n");  
  82.     printf("Get: %d\n", QueueGet());  
  83.     printf("Get: %d\n", QueueGet());  
  84.     printf("Get: %d\n", QueueGet());  
  85.     printf("Get: %d\n", QueueGet());  
  86.     system("pause");  
  87.     return 0;  
  88. }  


運行結果:


二、FIFO隊列的數組實現

隊列中的內容是數組中從head到tail的所有元素,到tail到達數組尾部時回捲到0,此程序的實現過程需要考慮隊列滿和隊列空兩種特殊狀態,
本文采用2種方式實現:

1)設定FIFO隊列的數組大小比客戶將在隊列放置的元素最大數目大1(From:《算法:C語言實現》P93)

 當head和tail重合時爲空;當tail+1和head重合時爲滿
FIFO_Array_1.cpp
[cpp] view plain copy
  1. /************************************************************* 
  2. From:《算法:C語言實現》 P93 
  3. 功能:先進先出隊列的數組形式實現:Init、Put、Get操作 
  4. 說明:  1)隊列中的內容是數組中從head到tail的所有元素,到tail到達數組尾部時回捲到0 
  5.     2)設定FIFO隊列的數組大小比客戶將在隊列放置的元素最大數目大1, 
  6.     當head和tail重合時爲空;當head和tail+1重合時爲滿 
  7. 時間: 2015/02/03 
  8. 作者: quinn 
  9. **************************************************************/  
  10. #include<stdio.h>  
  11. #include <stdlib.h>  
  12. const int maxN = 10; //FIFO size  
  13. typedef int Item;  
  14. static Item *q; //隊列  
  15. static int head, tail, N;  
  16. //隊列初始化,初始化數組、頭尾索引  
  17. void QueueInit(int maxN)  
  18. {  
  19.     q = (Item*)malloc(sizeof(*q) * (maxN+1));  
  20.     N = maxN + 1;  
  21.     head = N;  
  22.     tail = 0;  
  23. }  
  24.   
  25. //檢查隊列是否爲空  
  26. int QueueIsEmpty()  
  27. {  
  28.     return (head % N) == tail;  // Get操作中head++位於%操作之後;Put操作中tail++位於%操作之前  
  29. }  
  30. int QueueIsFull()  
  31. {  
  32.         return (tail + 1)%N == head % N;  
  33. }  
  34. //推入隊列,Put操作  
  35. void QueuePut(Item item)  
  36. {  
  37.     if (QueueIsFull())  
  38.     {  
  39.         printf("隊列已滿,Put: %d 操作失敗\n", item);  
  40.         return;  
  41.     }  
  42.     q[tail++] = item;  
  43.     tail %= N;  
  44.   
  45.     printf("Put: %d\n", item);  
  46. }  
  47. //出隊列,Get操作  
  48. Item QueueGet()  
  49. {  
  50.     if (QueueIsEmpty())  
  51.     {  
  52.         printf("此隊列現爲空,Get操作失敗,返回-1\n");  
  53.         return -1;  
  54.     }  
  55.     head %= N;  
  56.     return q[head++];  
  57. }  
  58.   
  59. //測試程序  
  60. int main()  
  61. {  
  62.     QueueInit(maxN);  
  63.     for (int i = 0; i <= 10; i++)  
  64.     {  
  65.         QueuePut(i);  
  66.     }  
  67.     printf("\n");  
  68.     printf("Get: %d\n\n", QueueGet());  
  69.     for (int i = 0; i < 10; i++)  
  70.     {  
  71.         printf("Get: %d\n", QueueGet());  
  72.     }  
  73.     system("pause");  
  74.     return 0;  
  75. }  
運行結果

2)設定FIFO隊列的數組大小和客戶將在隊列放置的元素最大數目相等

當put操作導致tail和head重合時,設定滿標誌flag_full = 1;(初始化設定flag_full= 0)
當get操作導致tail和head重合時,設定空標誌flag_empty = 1;(初始化設定flag_empty = 1)

FIFO_Array_2.cpp
[cpp] view plain copy
  1. /************************************************************* 
  2. 功能:先進先出隊列的數組形式實現:Init、Put、Get操作 
  3. 說明:1)設定FIFO隊列的大小,隊列中的內容是數組中從head到tail的 
  4.             所有元素,到tail到達數組尾部時回捲到0 
  5. 時間: 2015/02/03 
  6. 作者: quinn 
  7. **************************************************************/  
  8. #include<stdio.h>  
  9. #include <stdlib.h>  
  10. const int maxN = 10; //FIFO size  
  11. typedef int Item;  
  12. static Item *q;  
  13. static int head, tail;  
  14. static int flag_full = 0, flag_empty = 1; //隊列滿空標誌  
  15. //隊列初始化,初始化數組、頭尾索引  
  16. void QueueInit(int maxN)  
  17. {  
  18.     printf("初始化FIFO大小爲%d\n",maxN);  
  19.     q = (Item*)malloc(sizeof(*q) * maxN);  
  20.     head = 0;  
  21.     tail = 0;  
  22. }  
  23. //推入隊列,Put操作  
  24. void QueuePut(Item item)  
  25. {  
  26.     if (flag_full)  
  27.     {  
  28.         printf("隊列已滿,Put:%d 操作失敗\n",item);  
  29.         return;  
  30.     }  
  31.   
  32.     q[tail++] = item;  
  33.     tail %= maxN;  
  34.   
  35.     printf("Put: %d\n", item);  
  36.     flag_empty = 0; //put後非空  
  37.     if (tail  == head)//Put操作導致的head和tail重合時,隊列滿  
  38.     {  
  39.         flag_full = 1;  
  40.     }  
  41.   
  42. }  
  43.   
  44. //出隊列,Get操作  
  45. Item QueueGet()  
  46. {  
  47.   
  48.     if (flag_empty)  
  49.     {  
  50.         printf("隊列爲空,Get操作失敗,返回-1\n");  
  51.         return -1;  
  52.     }  
  53.   
  54.     head %= maxN;  
  55.   
  56.     flag_full = 0; //Get操作成功,滿標誌設爲0  
  57.     if ((head+1) % maxN == tail) //Get導致head+1和tail重合,隊列空  
  58.     {  
  59.         flag_empty = 1;  
  60.     }  
  61.   
  62.     return q[head++];  
  63.   
  64. }  
  65.   
  66. //測試程序  
  67. int main()  
  68. {  
  69.     QueueInit(maxN);  
  70.     for (int i = 0; i <= 10; i++)  
  71.     {  
  72.         QueuePut(i);  
  73.     }  
  74.     printf("\n");  
  75.     printf("Get: %d\n\n", QueueGet());  
  76.     for (int i = 0; i <= 10; i++)  
  77.     {  
  78.         printf("Get: %d\n", QueueGet());  
  79.     }  
  80.     system("pause");  
  81.     return 0;  
  82. }  

運行結果:



FIFO隊列ADT的get操作和put操作不論使用數組還是鏈表都能在常數時間內實現。

發佈了4 篇原創文章 · 獲贊 7 · 訪問量 8萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章