当前位置:   article > 正文

【数据结构和算法】认识队列,并实现循环队列_1)设计和实现一个队列数据结构,且采用循环队列实现,采用少用一个元素的方式进行存

1)设计和实现一个队列数据结构,且采用循环队列实现,采用少用一个元素的方式进行存

上接前文,我们学习了栈的相关知识内容,接下来,来认识一个与栈类似的,另一种特殊的线性表,队列,本文目的是了解并认识队列这一概念,并实现循环队列

目录

一、认识队列

1.队列的概念

2.队列的实现

二、实现循环队列

1.结构体格式以及初始化

2.队尾插入元素(入队)

3.队头删除数据(出队)

4.打印

5.清空队列、返回队头元素、返回队列元素个数

三、完整代码实现

总结


一、认识队列

1.队列的概念

队列:只允许在一端进行插入数据操作,在另一端进行删除数据操作的特殊的线性表,队列具有先进先出的特性,在队尾插入数据,称为入队,在队头删除数据,称为出队。

如图所示:

2.队列的实现

队列可以由两种方式来实现,分别可以由顺序表,和链表来实现,队列又分为循环队列,非循环队列。

区分:

1.非循环队列时,使用链表的结构实现更优一些,因为如果使用数组的结构,出队列在数组头上出数据,效率会低一点。

2.循环队列的时候,使用数组更加方便简洁,唯一缺点就是循环队列用数组的时候,只能是静态的数组,动态不能构成循环队列,当然可以使用循环链表

二、实现循环队列

我们使用数组的结构来实现循环队列

1.结构体格式以及初始化

代码如下:

  1. #define MAXSIZE 11//表示的是数组的元素个数,多一个1,是为了留给rear空间的
  2. typedef struct SqQueue {
  3. int data[MAXSIZE];
  4. int front;//队头
  5. int rear;//队尾 front 和 rear 就是指针(类似)
  6. }SqQueue;
  7. //初始化队列
  8. void InitQueue(SqQueue* ps) {
  9. //初始化队列只需要队头队尾都为0 表示下标起始位置
  10. ps->front = ps->rear = 0;
  11. }

实际上,我们使用的是静态数组,也只有这样我们才能实现循环队列,如果是动态数组,就无法实现循环效果,而且定义的MAXSIZE大小为11,有一个空间是不被存放数值的,作为一个标志。

2.队尾插入元素(入队)

最重要的一点是理解 

(rear+1)%MAXSIZE==front            这是判断队列是否为满队列的标志

如图所示:

 代码如下:

  1. //队尾插入元素
  2. void EnQueue(SqQueue* ps,int data) {
  3. //插入的时候先进行判满
  4. if ((ps->rear + 1) % MAXSIZE == ps->front) {//最多存储MAXSIZE-1个元素
  5. //表示已经满了
  6. perror("队列已经满了,无法加入新元素\n");
  7. exit(-1);//stdlib.h 头文件里面的
  8. }
  9. ps->data[ps->rear] = data;
  10. ps->rear = (ps->rear + 1) % MAXSIZE;
  11. }

3.队头删除数据(出队)

如图所示:

代码如下:

  1. //队头出队
  2. //只需要移动指针位置即可
  3. void OutQueue(SqQueue* ps, int* data) {
  4. //出队先判别是否为空
  5. if (ps->rear == ps->front) {
  6. perror("为空队列,无法出队\n");
  7. exit(-1);
  8. }
  9. *data = ps->data[ps->front];
  10. ps->front = (ps->front + 1) % MAXSIZE;
  11. //不需要整体移动只要将队头指针后移就可以
  12. }

4.打印

如图所示:

代码如下:

  1. //遍历打印元素
  2. void PrintQueue(SqQueue* ps) {
  3. int i = 0;
  4. printf("Queue->");
  5. while ((i + ps->front)%MAXSIZE != ps->rear) {
  6. //从front的队头位置开始,i从0开始 ++一直到等于rear结束
  7. printf("%d->", ps->data[i + ps->front]);
  8. i = (i + 1) % MAXSIZE;
  9. }
  10. printf("NULL\n");
  11. }

5.清空队列、返回队头元素、返回队列元素个数

代码如下:

  1. //将队列清空
  2. void ClearQueue(SqQueue* ps) {
  3. ps->front = ps->rear = 0;
  4. }
  5. //返回队头元素
  6. void GetHead(SqQueue* ps, int* data) {
  7. if (ps->front == ps->rear) {
  8. perror("为空队列\n");
  9. exit(-1);
  10. }
  11. *data = ps->data[ps->front];
  12. }
  13. //返回队列中的元素个数
  14. int CountSqQueue(SqQueue* ps) {
  15. return (ps->rear - ps->front + MAXSIZE) % MAXSIZE;
  16. }

三、完整代码实现

  1. #define _CRT_SECURE_NO_WARNINGS
  2. #include<stdio.h>
  3. #include<malloc.h>
  4. #include<assert.h>
  5. #include<stdlib.h>
  6. //构建的是循环队列,是使用数组的形式,完成的循环队列
  7. #define MAXSIZE 11//表示的是数组的元素个数,多一个1,是为了留给rear空间的
  8. typedef struct SqQueue {
  9. int data[MAXSIZE];
  10. int front;//队头
  11. int rear;//队尾 front 和 rear 就是指针(类似)
  12. }SqQueue;
  13. //初始化队列
  14. void InitQueue(SqQueue* ps) {
  15. //初始化队列只需要队头队尾都为0 表示下标起始位置
  16. ps->front = ps->rear = 0;
  17. }
  18. //将队列清空
  19. void ClearQueue(SqQueue* ps) {
  20. ps->front = ps->rear = 0;
  21. }
  22. //队尾插入元素
  23. void EnQueue(SqQueue* ps,int data) {
  24. //插入的时候先进行判满
  25. if ((ps->rear + 1) % MAXSIZE == ps->front) {//最多存储MAXSIZE-1个元素
  26. //表示已经满了
  27. perror("队列已经满了,无法加入新元素\n");
  28. exit(-1);//stdlib.h 头文件里面的
  29. }
  30. ps->data[ps->rear] = data;
  31. ps->rear = (ps->rear + 1) % MAXSIZE;
  32. }
  33. //队头出队
  34. //只需要移动指针位置即可
  35. void OutQueue(SqQueue* ps, int* data) {
  36. //出队先判别是否为空
  37. if (ps->rear == ps->front) {
  38. perror("为空队列,无法出队\n");
  39. exit(-1);
  40. }
  41. *data = ps->data[ps->front];
  42. ps->front = (ps->front + 1) % MAXSIZE;
  43. //不需要整体移动只要将队头指针后移就可以
  44. }
  45. //遍历打印元素
  46. void PrintQueue(SqQueue* ps) {
  47. int i = 0;
  48. printf("Queue->");
  49. while ((i + ps->front)%MAXSIZE != ps->rear) {
  50. //从front的队头位置开始,i从0开始 ++一直到等于rear结束
  51. printf("%d->", ps->data[i + ps->front]);
  52. i = (i + 1) % MAXSIZE;
  53. }
  54. printf("NULL\n");
  55. }
  56. //返回队头元素
  57. void GetHead(SqQueue* ps, int* data) {
  58. if (ps->front == ps->rear) {
  59. perror("为空队列\n");
  60. exit(-1);
  61. }
  62. *data = ps->data[ps->front];
  63. }
  64. //返回队列中的元素个数
  65. int CountSqQueue(SqQueue* ps) {
  66. return (ps->rear - ps->front + MAXSIZE) % MAXSIZE;
  67. }
  68. int main() {
  69. SqQueue Q;
  70. InitQueue(&Q);
  71. EnQueue(&Q, 1);
  72. EnQueue(&Q, 2);
  73. EnQueue(&Q, 3);
  74. EnQueue(&Q, 4);
  75. EnQueue(&Q, 5);
  76. PrintQueue(&Q);
  77. int a = 0;
  78. OutQueue(&Q, &a);
  79. PrintQueue(&Q);
  80. EnQueue(&Q, 1);
  81. EnQueue(&Q, 2);
  82. //EnQueue(&Q, 3);
  83. EnQueue(&Q, 4);
  84. EnQueue(&Q, 4);
  85. EnQueue(&Q, 5);
  86. EnQueue(&Q, 5);
  87. PrintQueue(&Q);
  88. }

总结

本文了解认识队列这一新的概念,我们也通过数组的结构实现循环队列,这一种方式实现循环队列是比较简单好理解的,主要的是理解MAXSIZE为什么要多一个空间,例如设置为11,还有判空,判满,操作。这是最为重要的。

判空:rear==front

判满:(rear+1)%MAXSIZE==front

得到队列元素个数:(rear-front+MAXSIZE)%MAXSIZE

front、rear、i得到下一个位置的方法:

例如:rear=(rear+1)%MAXSIZE

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

闽ICP备14008679号