[关闭]
@quinn 2015-03-20T09:28:36.000000Z 字数 4061 阅读 3977

FIFO 队列的链表和数组实现

数据结构


FIFO (First-in, First-out,先进先出)队列:当执行delete操作时删除那些呆在队列中时间最长的元素。
FIFO 队列是这样一个ADT,包含两个基本操作:插入(put)一个新的项、删除(get)一个最早插入的项。

一、FIFO队列的链表实现

FIFO 队列和下堆栈的区别在于新项的插入是在尾部,而不是在头部。因此实现程序要保存一个指向链表最后一个节点的尾指针tail ,因此当Put操作时,将tail 指针指向的next 指向新节点,然后更新tail指针,让它指向那个新的节点。

FIFO_LinkList.cpp

  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. Node* NewNode(Item item, Node* Next) // Next为插入的后一节点
  23. {
  24. Node* x = (Node*)malloc(sizeof(*x));//被插入的节点
  25. x->item = item;
  26. x->next = Next;
  27. return x;
  28. }
  29. //队列初始化
  30. void QueueInit(int maxN)
  31. {
  32. q = NULL;
  33. }
  34. //判断队列是否为空
  35. int QueueIsEmpty()
  36. {
  37. return (q == NULL);
  38. }
  39. //put操作
  40. void QueuePut( Item item)
  41. {
  42. if(QueueIsEmpty())
  43. {
  44. q = (tail = NewNode(item, q));
  45. }
  46. else
  47. {
  48. tail->next = NewNode(item, tail->next);
  49. tail = tail->next;
  50. }
  51. printf("Put: %d\n", item);
  52. }
  53. //get操作
  54. Item QueueGet()
  55. {
  56. if(q == NULL)
  57. {
  58. printf("序列为空!\n");
  59. return -1;
  60. }
  61. Item firstItem = q->item;//序列的头元素
  62. Node* tmpNode = q;
  63. q = q->next;
  64. free(tmpNode);
  65. return firstItem;
  66. }
  67. //测试程序
  68. int main()
  69. {
  70. QueueInit(maxN);
  71. QueuePut(2);
  72. QueuePut(3);
  73. QueuePut(4);
  74. printf("\n");
  75. printf("Get: %d\n", QueueGet());
  76. printf("Get: %d\n", QueueGet());
  77. printf("Get: %d\n", QueueGet());
  78. printf("Get: %d\n", QueueGet());
  79. system("pause");
  80. return 0;
  81. }

运行结果:
此处输入图片的描述

二、FIFO队列的数组实现

队列中的内容是数组中从head到tail的所有元素,到tail到达数组尾部时回卷到0,此程序的实现过程需要考虑队列满和队列空两种特殊状态,
本文采用2种方式实现:

1)设定FIFO队列的数组大小比客户将在队列放置的元素最大数目大1

(From:《算法:C语言实现》P93)

当head和tail重合时为空;当tail+1和head重合时为满
FIFO_Array_1.cpp

  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. int QueueIsEmpty()
  26. {
  27. return (head % N) == tail; // Get操作中head++位于%操作之后;Put操作中tail++位于%操作之前
  28. }
  29. int QueueIsFull()
  30. {
  31. return (tail + 1)%N == head % N;
  32. }
  33. //推入队列,Put操作
  34. void QueuePut(Item item)
  35. {
  36. if (QueueIsFull())
  37. {
  38. printf("队列已满,Put: %d 操作失败\n", item);
  39. return;
  40. }
  41. q[tail++] = item;
  42. tail %= N;
  43. printf("Put: %d\n", item);
  44. }
  45. //出队列,Get操作
  46. Item QueueGet()
  47. {
  48. if (QueueIsEmpty())
  49. {
  50. printf("此队列现为空,Get操作失败,返回-1\n");
  51. return -1;
  52. }
  53. head %= N;
  54. return q[head++];
  55. }
  56. //测试程序
  57. int main()
  58. {
  59. QueueInit(maxN);
  60. for (int i = 0; i <= 10; i++)
  61. {
  62. QueuePut(i);
  63. }
  64. printf("\n");
  65. printf("Get: %d\n\n", QueueGet());
  66. for (int i = 0; i < 10; i++)
  67. {
  68. printf("Get: %d\n", QueueGet());
  69. }
  70. system("pause");
  71. return 0;
  72. }

运行结果
此处输入图片的描述

2)设定FIFO队列的数组大小和客户将在队列放置的元素最大数目相等

当put操作导致tail和head重合时,设定满标志flag_full = 1;(初始化设定flag_full
= 0)
当get操作导致tail和head重合时,设定空标志flag_empty = 1;(初始化设定flag_empty = 1)

FIFO_Array_2.cpp

  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. q[tail++] = item;
  32. tail %= maxN;
  33. printf("Put: %d\n", item);
  34. flag_empty = 0; //put后非空
  35. if (tail == head)//Put操作导致的head和tail重合时,队列满
  36. {
  37. flag_full = 1;
  38. }
  39. }
  40. //出队列,Get操作
  41. Item QueueGet()
  42. {
  43. if (flag_empty)
  44. {
  45. printf("队列为空,Get操作失败,返回-1\n");
  46. return -1;
  47. }
  48. head %= maxN;
  49. flag_full = 0; //Get操作成功,满标志设为0
  50. if ((head+1) % maxN == tail) //Get导致head+1和tail重合,队列空
  51. {
  52. flag_empty = 1;
  53. }
  54. return q[head++];
  55. }
  56. //测试程序
  57. int main()
  58. {
  59. QueueInit(maxN);
  60. for (int i = 0; i <= 10; i++)
  61. {
  62. QueuePut(i);
  63. }
  64. printf("\n");
  65. printf("Get: %d\n\n", QueueGet());
  66. for (int i = 0; i <= 10; i++)
  67. {
  68. printf("Get: %d\n", QueueGet());
  69. }
  70. system("pause");
  71. return 0;
  72. }

运行结果:
此处输入图片的描述

FIFO队列ADT的get操作和put操作不论使用数组还是链表都能在常数时间内实现。

参考资料:《算法:C语言实现》 P93

添加新批注
在作者公开此批注前,只有你和作者可见。
回复批注