@quinn
2015-03-20T01:28:36.000000Z
字数 4061
阅读 4179
数据结构
FIFO (First-in, First-out,先进先出)队列:当执行delete操作时删除那些呆在队列中时间最长的元素。
FIFO 队列是这样一个ADT,包含两个基本操作:插入(put)一个新的项、删除(get)一个最早插入的项。
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;}
运行结果:
队列中的内容是数组中从head到tail的所有元素,到tail到达数组尾部时回卷到0,此程序的实现过程需要考虑队列满和队列空两种特殊状态,
本文采用2种方式实现:
(From:《算法:C语言实现》P93)
当head和tail重合时为空;当tail+1和head重合时为满
FIFO_Array_1.cpp
/*************************************************************From:《算法:C语言实现》 P93功能:先进先出队列的数组形式实现:Init、Put、Get操作说明: 1)队列中的内容是数组中从head到tail的所有元素,到tail到达数组尾部时回卷到02)设定FIFO队列的数组大小比客户将在队列放置的元素最大数目大1,当head和tail重合时为空;当head和tail+1重合时为满时间: 2015/02/03作者: quinn**************************************************************/#include<stdio.h>#include <stdlib.h>const int maxN = 10; //FIFO sizetypedef 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;}
运行结果
当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 sizetypedef 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操作成功,满标志设为0if ((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操作不论使用数组还是链表都能在常数时间内实现。
参考资料:《算法:C语言实现》 P93