当前位置:   article > 正文

详解循环队列

循环队列

目录

循环队列的概念

 循环队列的结构和基本运算

 循环队列的操作

循环队列的结构代码

初始化

入队

出队

队空

队满

队内元素的个数

获取对内头元素

输出队列

完整代码

效果截图​编辑

小结

参考文献


 

循环队列的概念

循环队列是一种特殊类型的队列数据结构,也被称为”唤醒缓冲器“。它在数组的基础实现了循环利用空间的功能。在循环队列中,队尾和队头之间形成了一个循环,当队尾指针“追上”队头指针时,队列不再继续增长,而是继续利用之前出队的空间。

 循环队列的结构和基本运算

  1. 队头指针(front):指向队头元素的位置。
  2. 队尾指针(rear):指向队尾元素的下一个位置,也就是即将插入新元素的位置。
  3. 入队操作会将元素插入到队尾指针所指向的位置,并将队尾指针后移。当队列满时,入队操作会失败。

  4. 出队操作会删除队头元素,并将队头指针后移。当队列为空时,出队操作会失败。

  5. 当队列为空时,front指针和rear指针同时指向下标为0的位置,因此循环队列为空的条件为front == rear
  6. 由于循环队列需要预留一个空间来区分队列为空和队列满的状态,队列满的条件为rear + 1 == head

 循环队列的操作

循环队列的结构代码
  1. #define MAXSIZE 100
  2. typedef int DataType;
  3. typedef struct
  4. {
  5. DataType data[MAXSIZE];
  6. int front;
  7. int rear;
  8. }CirclesQueue;
初始化
  1. int init(CirclesQueue *Q)
  2. {
  3. return 0;
  4. Q->front = Q->rear = 0;
  5. }
入队

入队操作会将元素插入到队尾指针所指向的位置,并将队尾指针后移。当队列满时,入队操作会失败。

  1. /*入队操作*/
  2. int enqueue(CirclesQueue *Q, DataType x)
  3. {
  4. if(isfull(Q))
  5. {
  6. printf("队列已满!100001\n");
  7. return 100001;
  8. }
  9. Q->rear = (Q->rear+1) % MAXSIZE;
  10. Q->data[Q->rear] = x;
  11. return 0;
  12. }
出队

出队操作会删除队头元素,并将队头指针后移。当队列为空时,出队操作会失败。

  1. /*出队操作*/
  2. int dequeue(CirclesQueue *Q, DataType *x)
  3. {
  4. if(isempty(Q))
  5. {
  6. printf("队列为空!100002\n");
  7. return 100002;
  8. }
  9. Q->front = (Q->front+1) % MAXSIZE;
  10. *x = Q->data[Q->front];
  11. return 0;
  12. }
队空

当队列为空时,front指针和rear指针同时指向下标为0的位置,因此循环队列为空的条件为front == rear

  1. /*判断队是否空*/
  2. int isempty(CirclesQueue *Q)
  3. {
  4. return (Q->front == Q->rear) ? 1 : 0;
  5. }
队满

队列满的条件为rear + 1 == head,尾指针像后移动一位,遇到头指针了。

  1. /*判断队是否满?*/
  2. int isfull(CirclesQueue *Q)
  3. {
  4. return (Q->rear+1)%MAXSIZE == Q->front ? 1 : 0;
  5. }
队内元素的个数

按照正常逻辑,计算队列长度只需要队尾减去队头即可,但是由于是循环队列,可能存在front大,rear小运算得出负数的情况,所以必须通过加上MAXSIZE再取余保证队列的大小为正数。

  1. /* 获取队列长度:循环队列:若rear在前方,则长度为rear-front+MAXSIZE,否则为rear-front */
  2. int getLength(CirclesQueue *Q) {
  3. return (Q->rear - Q->front + MAXSIZE) % MAXSIZE; /
  4. }
获取对内头元素
  1. /* 获取对内头元素 */
  2. DataType getFront(CirclesQueue* Q) {
  3. int i;
  4. i = (Q -> front) %MAXSIZE;
  5. return Q -> data[(i + 1 % MAXSIZE)];
  6. }
输出队列
  1. /* 输出队列内容 */
  2. void printQueue(CirclesQueue *Q) {
  3. int i;
  4. if (isempty(Q)) {
  5. printf("Queue is empty.\n");
  6. return;
  7. }
  8. i = (Q -> front) %MAXSIZE;
  9. do{
  10. printf(" %d",Q -> data[(i + 1 % MAXSIZE)]);
  11. i = (i+1) %MAXSIZE;
  12. }while(i != Q -> rear);
  13. }

完整代码

  1. /*
  2. main.c
  3. */
  4. #include <stdio.h>
  5. #include "CirclesQueue.h"
  6. #include <string.h>
  7. #include <stdlib.h>
  8. int main(int argc, char* argv[])
  9. {
  10. CirclesQueue Q;
  11. DataType x;
  12. int cmd;
  13. char yn;
  14. int result;
  15. char welcome[] = "\n\
  16. ★╭------╮☆☆☆☆☆☆╭------╮\n\
  17. ★╰╮八方来财╭╯◢ █ ◣◢ █ ◣╰╮期末高分╭╯\n\
  18. ★╭╯╰---╯╰╮██自 由██╭╯╰---╯╰╮\n\
  19. ★║◢ █ ◣◢ █ ◣║◥ █快乐█ ◤║◢ █ ◣◢ █ ◣║\n\
  20. ★║██████████║ ◥ ██ ◤ ║██████████║ \n\
  21. ★║◥ █真心█ ◤║  ║◥ █祝福█ ◤║\n\
  22. ★║ ◥ ██ ◤ ║☆ ☆ ☆ ☆ ☆║ ◥ ██ ◤ ║\n\
  23. ★║  ◥ ◤  ║☆ 事事如意☆ ║ ◥ ◤ ║\n\
  24. \\ ☆ 祝我 . 也祝你!☆\n\n";
  25. int i = 0;
  26. int m = 0;
  27. int n = 0;
  28. for(i=0;i<strlen(welcome);i++)
  29. {
  30. printf("%c",welcome[i]);
  31. for(m=0;m<10000;m++)
  32. for(n=0;n<1000;n++)
  33. {
  34. ;
  35. }
  36. }
  37. printf("\n\n\n");
  38. do
  39. {
  40. printf("-----------循环队列演示-----------\n");
  41. printf(" 1. 初始化\n");
  42. printf(" 2. 入队\n");
  43. printf(" 3. 出队\n");
  44. printf(" 4. 队空?\n");
  45. printf(" 5. 队满?\n");
  46. printf(" 6. 队列的元素个数\n");
  47. printf(" 7. 获取对内头元素\n");
  48. printf(" 8. 输出队列\n");
  49. printf(" 9. 帮助\n");
  50. printf(" 0. 退出\n");
  51. printf(" 请选择(0~9):");
  52. scanf("%d",&cmd);
  53. switch(cmd)
  54. {
  55. case 1:
  56. init(&Q);
  57. printf("队列已初始化!\n");
  58. break;
  59. case 2:
  60. printf("请输入要入队的元素x=");
  61. scanf("%d", &x);
  62. if(!enqueue(&Q,x))
  63. {
  64. printf("元素x=%d已入队\n", x);
  65. }
  66. break;
  67. case 3:
  68. printf("确定要出队(出队会将删除对首元素, y or n, n)?");
  69. getchar();
  70. scanf("%c", &yn);
  71. if(yn == 'y' || yn == 'Y')
  72. {
  73. if(!dequeue(&Q,&x))
  74. {
  75. printf("队首元素【%d】已出队!\n", x);
  76. }
  77. }
  78. break;
  79. case 4:
  80. if(isempty(&Q)) printf("队列为空!\n");
  81. else printf("队列不为空!\n");
  82. break;
  83. case 5:
  84. if(isfull(&Q)) printf("队列已满!\n");
  85. else printf("队列还没有满!\n");
  86. break;
  87. case 6:
  88. printf("队列的长度:%d\n",getLength(&Q));
  89. break;
  90. case 7:
  91. printf("获取对内头元素: %d\n", getFront(&Q));
  92. break;
  93. case 8:
  94. printf("输出队列:");
  95. printQueue(&Q);
  96. printf("\n");
  97. break;
  98. case 9:
  99. printf("本程序为循环队列的演示程序,由王路平设计开发!\n");
  100. break;
  101. }
  102. }while(cmd!=0);
  103. return 0;
  104. }
  105. /*
  106. CirclesQueue.h
  107. 循环队列
  108. */
  109. #define MAXSIZE 100
  110. typedef int DataType;
  111. typedef struct
  112. {
  113. DataType data[MAXSIZE];
  114. int front;
  115. int rear;
  116. }CirclesQueue;
  117. /*循环队列初始化*/
  118. int init(CirclesQueue *Q);
  119. /*入队*/
  120. int enqueue(CirclesQueue *Q, DataType x);
  121. /*队满?*/
  122. int isfull(CirclesQueue *Q);
  123. /*出队*/
  124. int dequeue(CirclesQueue *Q, DataType *);
  125. /*队空*/
  126. int isempty(CirclesQueue *Q);
  127. /* 输出队列内容 */
  128. void printQueue(CirclesQueue *Q);
  129. /* 获取队列长度 */
  130. int getLength(CirclesQueue *Q);
  131. /* 获取对内头元素 */
  132. DataType getFront(CirclesQueue* Q);
  133. /*
  134. CirclesQueue.c
  135. */
  136. #include "CirclesQueue.h"
  137. /*循环队列初始化*/
  138. int init(CirclesQueue *Q)
  139. {
  140. Q->front = Q->rear = 0;
  141. return 0;
  142. }
  143. /*入队*/
  144. int enqueue(CirclesQueue *Q, DataType x)
  145. {
  146. if(isfull(Q))
  147. {
  148. printf("队列已满!100001\n");
  149. return 100001;
  150. }
  151. Q->rear = (Q->rear+1) % MAXSIZE;
  152. Q->data[Q->rear] = x;
  153. return 0;
  154. }
  155. /*出队*/
  156. int dequeue(CirclesQueue *Q, DataType *x)
  157. {
  158. if(isempty(Q))
  159. {
  160. printf("队列为空!100002\n");
  161. return 100002;
  162. }
  163. Q->front = (Q->front+1) % MAXSIZE;
  164. *x = Q->data[Q->front];
  165. return 0;
  166. }
  167. /*队空*/
  168. int isempty(CirclesQueue *Q)
  169. {
  170. return (Q->front == Q->rear) ? 1 : 0;
  171. }
  172. /*队满?*/
  173. int isfull(CirclesQueue *Q)
  174. {
  175. return (Q->rear+1)%MAXSIZE == Q->front ? 1 : 0;
  176. }
  177. /* 获取队列长度:循环队列:若rear在前方,则长度为rear-front+MAXSIZE,否则为rear-front */
  178. int getLength(CirclesQueue *Q) {
  179. return (Q->rear - Q->front + MAXSIZE) % MAXSIZE;
  180. }
  181. /* 获取对内头元素 */
  182. DataType getFront(CirclesQueue* Q) {
  183. int i;
  184. i = (Q -> front) %MAXSIZE;
  185. return Q -> data[(i + 1 % MAXSIZE)];
  186. }
  187. /* 输出队列内容 */
  188. void printQueue(CirclesQueue *Q) {
  189. int i;
  190. if (isempty(Q)) {
  191. printf("Queue is empty.\n");
  192. return;
  193. }
  194. i = (Q -> front) %MAXSIZE;
  195. do{
  196. printf(" %d",Q -> data[(i + 1 % MAXSIZE)]);
  197. i = (i+1) %MAXSIZE;
  198. }while(i != Q -> rear);
  199. }

效果截图

小结

本次学习了循环队列,了解了循环队列的入队,出队,队空,队满等基本操作,明白了循环队列的优点在于其高效的插入和删除操作,但需要注意的是在实现时需要处理满队列和空队列的情况。此外,循环队列也需要一些技巧来扩展其容量,例如使用多级循环队列等。

参考文献

循环队列详解_Forward♞的博客-CSDN博客

队列之循环队列详解(C语言版)-CSDN博客

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/你好赵伟/article/detail/412792
推荐阅读
相关标签
  

闽ICP备14008679号