FIFO (First-in, First-out,先進先出)隊列:當執行delete操作時刪除那些呆在隊列中時間最長的元素。
FIFO 隊列是這樣一個ADT,包含兩個基本操作:插入(put)一個新的項、刪除(get)一個最早插入的項。
一、FIFO隊列的鏈表實現
FIFO 隊列和下堆棧的區別在於新項的插入是在尾部,而不是在頭部。因此實現程序要保存一個指向鏈表最後一個節點的尾指針tail ,因此當Put操作時,將tail 指針指向的next 指向新節點,然後更新tail指針,讓它指向那個新的節點。
FIFO_LinkList.cpp
- /*************************************************************
- 功能:先進先出隊列的鏈表形式實現:Init、Put、Get操作
- 說明: 從頭部Get,從尾部Put
- 時間: 2015/02/03
- 作者: quinn
- **************************************************************/
- #include<stdio.h>
- #include<malloc.h>
- #include<stdlib.h>
- typedef int Item;
- typedef struct Node Node;
- typedef Node* Queue;
- struct Node //節點結構
- {
- Item item;
- Node* next;
- };
- static int maxN = 10;
- static Queue q = NULL;
- static Node* tail = NULL;
- //新建一個節點
- Node* NewNode(Item item, Node* Next) // Next爲插入的後一節點
- {
- Node* x = (Node*)malloc(sizeof(*x));//被插入的節點
- x->item = item;
- x->next = Next;
- return x;
- }
- //隊列初始化
- void QueueInit(int maxN)
- {
- q = NULL;
- }
- //判斷隊列是否爲空
- int QueueIsEmpty()
- {
- return (q == NULL);
- }
- //put操作
- void QueuePut( Item item)
- {
- if(QueueIsEmpty())
- {
- q = (tail = NewNode(item, q));
- }
- else
- {
- tail->next = NewNode(item, tail->next);
- tail = tail->next;
- }
- printf("Put: %d\n", item);
- }
- //get操作
- Item QueueGet()
- {
- if(q == NULL)
- {
- printf("序列爲空!\n");
- return -1;
- }
- Item firstItem = q->item;//序列的頭元素
- Node* tmpNode = q;
- q = q->next;
- free(tmpNode);
- return firstItem;
- }
- //測試程序
- int main()
- {
- QueueInit(maxN);
- QueuePut(2);
- QueuePut(3);
- QueuePut(4);
- printf("\n");
- printf("Get: %d\n", QueueGet());
- printf("Get: %d\n", QueueGet());
- printf("Get: %d\n", QueueGet());
- printf("Get: %d\n", QueueGet());
- system("pause");
- return 0;
- }
運行結果:
二、FIFO隊列的數組實現
隊列中的內容是數組中從head到tail的所有元素,到tail到達數組尾部時回捲到0,此程序的實現過程需要考慮隊列滿和隊列空兩種特殊狀態,
FIFO_Array_1.cpp
- /*************************************************************
- From:《算法:C語言實現》 P93
- 功能:先進先出隊列的數組形式實現:Init、Put、Get操作
- 說明: 1)隊列中的內容是數組中從head到tail的所有元素,到tail到達數組尾部時回捲到0
- 2)設定FIFO隊列的數組大小比客戶將在隊列放置的元素最大數目大1,
- 當head和tail重合時爲空;當head和tail+1重合時爲滿
- 時間: 2015/02/03
- 作者: quinn
- **************************************************************/
- #include<stdio.h>
- #include <stdlib.h>
- const int maxN = 10; //FIFO size
- typedef int Item;
- static Item *q; //隊列
- static int head, tail, N;
- //隊列初始化,初始化數組、頭尾索引
- void QueueInit(int maxN)
- {
- q = (Item*)malloc(sizeof(*q) * (maxN+1));
- N = maxN + 1;
- head = N;
- tail = 0;
- }
- //檢查隊列是否爲空
- int QueueIsEmpty()
- {
- return (head % N) == tail; // Get操作中head++位於%操作之後;Put操作中tail++位於%操作之前
- }
- int QueueIsFull()
- {
- return (tail + 1)%N == head % N;
- }
- //推入隊列,Put操作
- void QueuePut(Item item)
- {
- if (QueueIsFull())
- {
- printf("隊列已滿,Put: %d 操作失敗\n", item);
- return;
- }
- q[tail++] = item;
- tail %= N;
- printf("Put: %d\n", item);
- }
- //出隊列,Get操作
- Item QueueGet()
- {
- if (QueueIsEmpty())
- {
- printf("此隊列現爲空,Get操作失敗,返回-1\n");
- return -1;
- }
- head %= N;
- return q[head++];
- }
- //測試程序
- int main()
- {
- QueueInit(maxN);
- for (int i = 0; i <= 10; i++)
- {
- QueuePut(i);
- }
- printf("\n");
- printf("Get: %d\n\n", QueueGet());
- for (int i = 0; i < 10; i++)
- {
- printf("Get: %d\n", QueueGet());
- }
- system("pause");
- return 0;
- }
2)設定FIFO隊列的數組大小和客戶將在隊列放置的元素最大數目相等
當put操作導致tail和head重合時,設定滿標誌flag_full = 1;(初始化設定flag_full= 0)
當get操作導致tail和head重合時,設定空標誌flag_empty = 1;(初始化設定flag_empty = 1)
FIFO_Array_2.cpp
- /*************************************************************
- 功能:先進先出隊列的數組形式實現:Init、Put、Get操作
- 說明:1)設定FIFO隊列的大小,隊列中的內容是數組中從head到tail的
- 所有元素,到tail到達數組尾部時回捲到0
- 時間: 2015/02/03
- 作者: quinn
- **************************************************************/
- #include<stdio.h>
- #include <stdlib.h>
- const int maxN = 10; //FIFO size
- typedef int Item;
- static Item *q;
- static int head, tail;
- static int flag_full = 0, flag_empty = 1; //隊列滿空標誌
- //隊列初始化,初始化數組、頭尾索引
- void QueueInit(int maxN)
- {
- printf("初始化FIFO大小爲%d\n",maxN);
- q = (Item*)malloc(sizeof(*q) * maxN);
- head = 0;
- tail = 0;
- }
- //推入隊列,Put操作
- void QueuePut(Item item)
- {
- if (flag_full)
- {
- printf("隊列已滿,Put:%d 操作失敗\n",item);
- return;
- }
- q[tail++] = item;
- tail %= maxN;
- printf("Put: %d\n", item);
- flag_empty = 0; //put後非空
- if (tail == head)//Put操作導致的head和tail重合時,隊列滿
- {
- flag_full = 1;
- }
- }
- //出隊列,Get操作
- Item QueueGet()
- {
- if (flag_empty)
- {
- printf("隊列爲空,Get操作失敗,返回-1\n");
- return -1;
- }
- head %= maxN;
- flag_full = 0; //Get操作成功,滿標誌設爲0
- if ((head+1) % maxN == tail) //Get導致head+1和tail重合,隊列空
- {
- flag_empty = 1;
- }
- return q[head++];
- }
- //測試程序
- int main()
- {
- QueueInit(maxN);
- for (int i = 0; i <= 10; i++)
- {
- QueuePut(i);
- }
- printf("\n");
- printf("Get: %d\n\n", QueueGet());
- for (int i = 0; i <= 10; i++)
- {
- printf("Get: %d\n", QueueGet());
- }
- system("pause");
- return 0;
- }
運行結果:
FIFO隊列ADT的get操作和put操作不論使用數組還是鏈表都能在常數時間內實現。