FIFO (First-in, First-out,先进先出)队列:当执行delete操作时删除那些呆在队列中时间最长的元素。
FIFO 队列是这样一个ADT,包含两个基本操作:插入(put)一个新的项、删除(get)一个最早插入的项。
一、FIFO队列的链表实现
FIFO 队列和下堆栈的区别在于新项的插入是在尾部,而不是在头部。因此实现程序要保存一个指向链表最后一个节点的尾指针tail ,因此当Put操作时,将tail 指针指向的next 指向新节点,然后更新tail指针,让它指向那个新的节点。
FIFO_LinkList.cpp
-
-
-
-
-
-
- #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)
- {
- 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);
- }
-
-
- 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);
- }
-
-
- 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,此程序的实现过程需要考虑队列满和队列空两种特殊状态,
本文采用2种方式实现:
1)设定FIFO队列的数组大小比客户将在队列放置的元素最大数目大1(From:《算法:C语言实现》P93)
当head和tail重合时为空;当tail+1和head重合时为满
FIFO_Array_1.cpp
-
-
-
-
-
-
-
-
-
- #include<stdio.h>
- #include <stdlib.h>
- const int maxN = 10;
- 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;
- }
- int QueueIsFull()
- {
- return (tail + 1)%N == head % N;
- }
-
- void QueuePut(Item item)
- {
- if (QueueIsFull())
- {
- printf("队列已满,Put: %d 操作失败\n", item);
- return;
- }
- q[tail++] = item;
- tail %= N;
-
- printf("Put: %d\n", item);
- }
-
- 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
-
-
-
-
-
-
-
- #include<stdio.h>
- #include <stdlib.h>
- const int maxN = 10;
- 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;
- }
-
- 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;
- if (tail == head)
- {
- flag_full = 1;
- }
-
- }
-
-
- Item QueueGet()
- {
-
- if (flag_empty)
- {
- printf("队列为空,Get操作失败,返回-1\n");
- return -1;
- }
-
- head %= maxN;
-
- flag_full = 0;
- if ((head+1) % maxN == 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操作不论使用数组还是链表都能在常数时间内实现。