深圳幻海软件技术有限公司 欢迎您!

循环队列详解

2023-04-05

概述1.先进先出的线性序列,称为队列,队列也是一种线性表,只不过它是操作受限的线性表,只能在两端操作。一端进,一端出。进的一端称为队尾,出的一端称为队头,队列可以用顺序存储也可以用链式存储。2.队列的顺序存储形式,可以用一段连续的空间存储数据元素,用两个整型变量记录队头和队尾元素的下标。3初始化(1

概述

1.先进先出的线性序列,称为队列,队列也是一种线性表,只不过它是操作受限的线性表,只能在两端操作。一端进,一端出。进的一端称为队尾,出的一端称为队头,队列可以用顺序存储也可以用链式存储。

2.队列的顺序存储形式,可以用一段连续的空间存储数据元素,用两个整型变量记录队头和队尾元素的下标。

3初始化

(1)

base为数组的基地址,front,base分别代表指向队头和队尾的"指针"(数组下标),构造空队列只需要申请一块内存给基地址,并且将队头指针与队尾指针赋值为0.

 

(2)

因为该队列为循环队列所以

 

  1. typedef struct SqQueue
  2. {
  3. int* base;
  4. int front, rear;
  5. }SqQueue;
  6. //构造空队列
  7. bool InitQueue(SqQueue& Q)
  8. {
  9. Q.base = new int[Maxsize];
  10. if (Q.base == NULL)
  11. {
  12. return false;
  13. }
  14. Q.front = Q.rear = 0;
  15. return true;
  16. }

 4入队

 (1)将队尾指向的位置赋值,并且赋值后将队尾的位置后移

 

 (2)在入队时难免会出现以下情况

 队列的空间未利用完,但是却造成了元素的溢出(又称"假溢出"),所以要利用循环队列,这样就不会有这样的顾虑

 入队的操作为

Q.base[Q.rear]=e;  将元素e放入Q.rear指向的空间

Q.rear=(Q.rear+1)%Maxsize rear指针向后移动一个单位

至于为什么要加对(Q.rear+1)取模,这是因为rear指针会一直增加到比队列容量大的数字,对其取模就是为了使其缩小,指向真正的位置例如 容量大小为5 队尾指向9 取模队尾指向的是4,说明队尾指正已经走过了一个圈

tips:在入队前要判断队列是否为空怎们办

如图此时队尾指向的是循环队列的最后一个空间,这个空间并没有存放任何数据,判断队列是否为满只要将队尾指针+1看看其是否与队头相等,此处为什么要取模?

例如队列空间大小为10,队尾指向第10个空间,下标为9,对其加1等于10,取模等于0,此时队头也是指向0的所以需要取模

有例如如果一开始队头指向的是1,队尾指向的是0,那么队尾加1,取模后为1,那么此时对也满

 

  1. //入队
  2. bool Push(SqQueue& Q, int e)
  3. {
  4. if ((Q.rear + 1) % Maxsize == Q.front)
  5. {
  6. cout << "队满" << endl;
  7. return false;
  8. }
  9. Q.base[Q.rear] = e;
  10. Q.rear = (Q.rear + 1) % Maxsize;
  11. return true;
  12. }

5出队

出队前判断队列是否为空

当尾指针与头指针指向一起时队空,注意与队满的区别

出队的操作

e=Q.base[Q.front];

Q.front=[Q.front+1]%Maxsize;

将头指针向着元素增长方向移动一个单元,原来的头指针指向的元素并没有真正的删除,只是逻辑上的删除,后序如果要用到这个空间,会用新的元素将其覆盖掉

至于为什么要用取模和上述的入队是一致的

 

  1. bool Pop(SqQueue& Q, int& e)
  2. {
  3. if (Q.rear == Q.front)
  4. {
  5. cout << "队空" << endl;
  6. return false;
  7. }
  8. e = Q.base[Q.front];
  9. Q.front = (Q.front + 1) % Maxsize;
  10. }

6.获取队头元素

判断队列是否为空

简单的数组取元素而已

  1. int Get_front(SqQueue Q)
  2. {
  3. if (Q.rear == Q.front)
  4. {
  5. cout << "队空" << endl;
  6. return -1;
  7. }
  8. return Q.base[Q.front];
  9. }

7.获取队尾元素

判断队列是否为空

因为队尾一直指向最后一个元素的后一个位置,所以要去指正前面的空间,就是队尾元素

  1. int Get_back(SqQueue Q)
  2. {
  3. if (Q.front == Q.rear)
  4. {
  5. cout << "队空" << endl;
  6. return -1;
  7. }
  8. return Q.base[Q.rear - 1];
  9. }

8.获取队列元素个数

这两段的代码意思是一样的

因为队尾减队头可能会出现负数,所以需要加上容量大小后取模,这样才会得到真实的容量大小

例如队列大小6,队尾指向1,队头指向2,那么元素个数为(1-2+6)%6=5个

例如队列大小6,队尾指向5,队头指向0,那么元素个数为(5-0+6)%6=5个

  1. int length(SqQueue Q)
  2. {
  3. return (Q.rear - Q.front + MaxSize) % MaxSize;
  4. /*if (Q.rear - Q.front >= 0)
  5. {
  6. return Q.rear - Q.front;
  7. }
  8. else
  9. {
  10. return (Q.rear - Q.front + MaxSize);
  11. }*/
  12. }

完整代码如下

  1. #define _CRT_SECURE_NO_WARNINGS
  2. #include<iostream>
  3. #include<algorithm>
  4. using namespace std;
  5. const int MaxSize = 100;
  6. typedef struct SqQueue
  7. {
  8. int* base;
  9. int front, rear;
  10. }SqQueue;
  11. bool InitQueue(SqQueue& Q)
  12. {
  13. Q.base = new int[MaxSize];
  14. if (Q.base == NULL)
  15. {
  16. return false;
  17. }
  18. Q.front = Q.rear = 0;
  19. return true;
  20. }
  21. bool Push(SqQueue& Q, int e)
  22. {
  23. if ((Q.rear + 1) % MaxSize == Q.front)
  24. {
  25. return false;
  26. }
  27. Q.base[Q.rear] = e;
  28. Q.rear = (Q.rear + 1) % MaxSize;
  29. return true;
  30. }
  31. bool Pop(SqQueue& Q, int& e)
  32. {
  33. if (Q.rear == Q.front)
  34. {
  35. return false;
  36. }
  37. e = Q.base[Q.front];
  38. Q.front = (Q.front + 1) % MaxSize;
  39. }
  40. int Get_front(SqQueue Q)
  41. {
  42. if (Q.front == Q.rear)
  43. {
  44. return -1;
  45. }
  46. return Q.base[Q.front];
  47. }
  48. int Get_back(SqQueue Q)
  49. {
  50. if (Q.front == Q.rear)
  51. {
  52. return -1;
  53. }
  54. return Q.base[Q.rear - 1];
  55. }
  56. int length(SqQueue Q)
  57. {
  58. return (Q.rear - Q.front + MaxSize) % MaxSize;
  59. /*if (Q.rear - Q.front >= 0)
  60. {
  61. return Q.rear - Q.front;
  62. }
  63. else
  64. {
  65. return (Q.rear - Q.front + MaxSize);
  66. }*/
  67. }
  68. int main()
  69. {
  70. SqQueue S;
  71. InitQueue(S);
  72. int n = 0;
  73. cout << "请输入有多少元素" << endl;
  74. cin >> n;
  75. cout << "依次输入元素" << endl;
  76. while (n--)
  77. {
  78. int e;
  79. cin >> e;
  80. Push(S, e);
  81. }
  82. int L = length(S);
  83. for (int i = 0; i < L; i++)
  84. {
  85. cout << "队尾:"<<Get_back(S) << " "<<"队头:"<<Get_front(S)<<"---";
  86. int e = 0;
  87. Pop(S, e);
  88. cout << e <<" ";
  89. cout << endl;
  90. }
  91. //cout << length(S);
  92. cout << endl;
  93. system("pause");
  94. return EXIT_SUCCESS;
  95. }

文章知识点与官方知识档案匹配,可进一步学习相关知识
算法技能树首页概览43103 人正在系统学习中