【数据结构】之循环队列的实现(C语言)

灰太狼 2023-02-15 12:39 75阅读 0赞

文章目录

    • 顺序存储队列的缺点
    • 循环队列定义
      • 完整代码

顺序存储队列的缺点

我们假设一个队列有n个元素,则顺序存储的队列需建立一个大于n的数组,并把队列的所有元素存储在数组的前n个单元,数组下标为0的一端即时对头,所谓的入队操作,其实就是在队尾追加一个元素,不需要移动任何元素。
在这里插入图片描述
与栈不同的是,队列出队元素是在对头,即下标为0的位置,那也就意味着,队列中所有的元素都得向前移动,以保证队列的对头,也就是下标为0的位置不为空。
在这里插入图片描述
为了避免当只有一个元素时,队头和队尾重合使处理变的麻烦,所以引入两个指针,front指针指向对头元素,rear指针指向队尾元素的下一个位置,这样放front = rear时,此队列为空。

假设长度为5的数组,初始状态如下左图所示,front与rear指针均指向下标为0的位置。然后入队a1,a2,a3,a4,front指针依然指向下标为0的位置,而rear指针指向下标为4的位置。
在这里插入图片描述
出队a1,a2,则front指针指向下标为2的位置,rear不变,如下图左图。在入队a5,此时front指针不变,rear指针移动到数组之外,此时产生数组越界的错误,可实际上,队列的下标0和1的地方还是空闲的,这种现象称为“假溢出”
在这里插入图片描述

循环队列定义

解决假溢出的办法就是后面满了,在重头开始,也就是首尾相接的循环。
我们把队列的这种首尾相接的顺序存储结构称为循环队列。

上面的例子,把rear的指向改为下标为0的位置。
在这里插入图片描述
接着入队a6,将它放置于下标为0处,rear指针指向下标为1处。若在入队a7,则rear指针就与front指针重合,同时指向下标为2的位置。
在这里插入图片描述
那么问题来了,此时如何判断队列是空还是满呢?

  • 一:设置一个标识变量flag,当front == rear,且flag=0时队列为空,当front==rear,且flag =1时为队满。
  • 二:当队列为空时,条件就是front=rear,队列满时,我们修改其条件,保留一个元素空间。也就是说,队列满时,数组中还有一个空闲单元。如下图所示。
    在这里插入图片描述

一般采用第二种办法,由于rear可能比front大,也可能比front小,所以尽管他们只相差一个位置时就是满的情况,但是也可能相差整整一圈。
设队列的最大容量为QueneSize,那么队满的条件是(rear+1)%QueneSize ==front (取模%的目的视为了整合rear与front大小为一个问题)

通用的计算队列的长度公式为
(rear-front+QueneSize)%QueneSize

循环队列的顺序存储结构代码如下

  1. typedef int QElemType //QElemType根据实际定,这里设为int
  2. //存储结构
  3. typedef struct
  4. {
  5. QElemType data[MAXSIZE];
  6. int front; //头指针
  7. int rear //尾指针,若队列不为空,指向队尾元素的下一个位置
  8. }SqQuene

循环队列的初始化代码

  1. //初始化一个空队列
  2. Status InitQueneSqQuene *Q
  3. {
  4. Q->front=0
  5. Q->rear=0;
  6. return OK;
  7. }

求循环队列长度

  1. //返回Q的元素个数,也就是队列的当前长度
  2. int QueneLength(SqQuene Q)
  3. {
  4. return (Q.rear - Q.front +MAXSIZE)%MAXSIZE;
  5. }

入队操作

  1. Ststus EnQuene(SqQuene *Q,QElemType e)
  2. {
  3. if(Q->rear+1%MAXSIZE == Q->front) //判断队满
  4. return ERROR;
  5. Q->data[Q->rear] =e; //元素e赋值给队尾
  6. Q->rear=(Q->rear+1)%MAXSIZE //rear指向后移
  7. return OK;
  8. }

出队操作

  1. Ststus DeQuene(SqQuene *Q,QElemType e)
  2. {
  3. if(Q->front == Q->rear) //判断队空
  4. return ERROR;
  5. *e=Q->data[Q->front]; //队头元素赋值给e
  6. Q->front=(Q->front+1)%MAXSIZE; //front后移
  7. }

完整代码

  1. #include <stdio.h>
  2. #include <malloc.h>
  3. typedef int QElemType;
  4. typedef int Status;
  5. #define MaxQSize 10
  6. #define OK 1
  7. #define ERROR 0
  8. #define TRUE 1
  9. #define FALSE 0
  10. #define OVERFLOW -1
  11. typedef struct
  12. {
  13. QElemType *base;
  14. int front, rear;
  15. }SqQueue;
  16. //初始化循环队列
  17. Status InitQueue(SqQueue &Q)
  18. {
  19. Q.base = (QElemType*)malloc(MaxQSize*sizeof(QElemType));
  20. if (Q.base == NULL)
  21. {
  22. puts("分配内存空间失败!");
  23. exit(OVERFLOW);
  24. }
  25. Q.front = Q.rear = 0;
  26. return 0;
  27. }
  28. //将循环队列清空
  29. Status ClearQueue(SqQueue &Q)
  30. {
  31. Q.front = Q.rear = 0;
  32. }
  33. //求队列元素的个数
  34. Status QueueLength(SqQueue Q)
  35. {
  36. return (Q.rear - Q.front + MaxQSize) % MaxQSize;
  37. }
  38. //插入元素到循环队列
  39. Status EnSqQueue(SqQueue &Q, QElemType e)
  40. {
  41. if ((Q.rear + 1) % MaxQSize == Q.front){
  42. puts("队列已满!"); return ERROR; /*队列满*/}
  43. Q.base[Q.rear] = e; //元素e入队
  44. Q.rear = (Q.rear + 1) % MaxQSize; //修改队尾指针
  45. return OK;
  46. }
  47. //从循环队列中删除元素
  48. Status DeSqQueue(SqQueue &Q, QElemType &e)
  49. {
  50. if (Q.front == Q.rear)
  51. return ERROR;
  52. e = Q.base[Q.front]; //取队头元素至e
  53. Q.front = (Q.front + 1) % MaxQSize; //修改队头指针,如果超内存,循环
  54. return OK;
  55. }
  56. //判断一个循环队列是否为空队列
  57. Status isQueueEmpty(SqQueue Q)
  58. {
  59. if (Q.front == Q.rear)
  60. return TRUE;
  61. else
  62. return FALSE;
  63. }
  64. int main()
  65. {
  66. int i, e;
  67. SqQueue Q;
  68. InitQueue(Q);
  69. for (i=0; i<MaxQSize; i++) //只有MaxQSize个数据进队列
  70. EnSqQueue(Q, i);
  71. i = QueueLength(Q);
  72. printf("队列里的元素有%d个\n", i);
  73. for (i=0; i<3; i++)
  74. {
  75. DeSqQueue(Q, e);
  76. printf("%d ", e);
  77. }
  78. printf("\n");
  79. i = QueueLength(Q);
  80. printf("队列里的元素有%d个\n", i);
  81. for (i=10; i<12; i++)
  82. EnSqQueue(Q, i);
  83. i = QueueLength(Q);
  84. printf("队列里的元素有%d个\n", i);
  85. ClearQueue(Q);
  86. i = QueueLength(Q);
  87. printf("队列里的元素有%d个\n", i);
  88. return 0;
  89. }

发表评论

表情:
评论列表 (有 0 条评论,75人围观)

还没有评论,来说两句吧...

相关阅读