• 【数据结构初阶】顺序循环队列和链式循环队列


    目录

    1.知识点

    2.顺序循环队列

    3.链式循环队列

     4.一道妙的选择题


    1.知识点

    让我们先对比一下普通队列和循环队列

     普通队列的实现,不懂可以戳这里https://blog.csdn.net/qq_64428099/article/details/126173181

    第一个问题:顺序循环队列和链式循环队里怎么做到循环?

    循环队列是定长的数组,循环数组在循环方面物理上肯定不能做到循环,所以我们采用逻辑上循环的方式,当tail或者front到了边界的时候,手动"拉到"合适的位置,逻辑上造成一种循环.

    而循环链表在循环方面物理上是可以做到循环的(循环链表)
    而逻辑上就更是自动->next就能回到合适的位置造成循环.


    第二个问题:由于循环队列是定长的,定长的话和普通队列不一样,不定长的话,只用考虑为队列空的情况,定长的话,除了考虑为空的情况,还需要考虑队列为满的情况.

    至于如何判断队列为空和队列满了?请往下看

     

    回顾一下我们以前队列判空的逻辑:(指向同一个值为空的数组元素或者节点

    顺序普通队列:a[front]==a[tail]

    链式普通队列:front==tail

    如果我们和之前一样的方式判断满的话,我们会发现

    这判断队列满的方式怎么和判断队列空的方式一模一样,这可怎么整啊!倒时候没办法区分不是乱套了吗?!别急,有办法~~

    解决判断队列为空和队列满有两种解决方案:

    1. 方法一:
      在MyCircularQueue结构体中设置一个size成员变量,用于记录实际的元素个数,而定长K是题目会给的,我们也相应的记录为capacity就行了,空就是size==0;满就是size==capacity;
    2. 方法二
      多开一个空间,使得满的时候永远有一个位置不存数据,就好比这样就是满了

    下面以方法2为例:

     特别注意:这里的方法二中的满的时候永远空出一个空间,不一定是最后一个空间!
     当入队列时有元素出队列时此时就可以使得空出的那一个位置不是最后那个空间!例如上图链式循环队列.

    2.顺序循环队列

    设计循环队列https://leetcode.cn/problems/design-circular-queue/submissions/

    1. typedef struct {
    2. int* a;
    3. int k;
    4. int front;
    5. int tail;
    6. } MyCircularQueue;
    7. MyCircularQueue* myCircularQueueCreate(int k) {
    8. MyCircularQueue* obj=(MyCircularQueue*)malloc(sizeof(MyCircularQueue));
    9. obj->a=(int*)malloc(sizeof(int)*(k+1));
    10. obj->k=k;
    11. obj->front=obj->tail=0;
    12. return obj;
    13. }
    14. bool myCircularQueueIsFull(MyCircularQueue* obj);
    15. bool myCircularQueueEnQueue(MyCircularQueue* obj, int value) {
    16. if(myCircularQueueIsFull(obj))
    17. {
    18. return false;
    19. }
    20. else
    21. {
    22. obj->a[obj->tail]=value;
    23. //书写方式1:
    24. // obj->tail++;
    25. // if(obj->tail==obj->k+1)
    26. // {
    27. // obj->tail=0;
    28. // }
    29. //书写方式2:
    30. obj->tail=(obj->tail+1)%(obj->k+1);
    31. return true;
    32. }
    33. }
    34. bool myCircularQueueIsEmpty(MyCircularQueue* obj) ;
    35. bool myCircularQueueDeQueue(MyCircularQueue* obj) {
    36. if(myCircularQueueIsEmpty(obj))
    37. {
    38. return false;
    39. }
    40. else
    41. {
    42. //书写方式1:
    43. // obj->front++;
    44. // if(obj->front==obj->k+1)
    45. // {
    46. // obj->front=0;
    47. // }
    48. //书写方式2:
    49. obj->front=(obj->front+1)%(obj->k+1);
    50. return true;
    51. }
    52. }
    53. int myCircularQueueFront(MyCircularQueue* obj) {
    54. if(myCircularQueueIsEmpty(obj))
    55. {
    56. return -1;
    57. }
    58. else
    59. {
    60. return obj->a[obj->front];
    61. }
    62. }
    63. int myCircularQueueRear(MyCircularQueue* obj) {
    64. if(myCircularQueueIsEmpty(obj))
    65. {
    66. return -1;
    67. }
    68. else
    69. {
    70. // int tailPrev=obj->tail-1;
    71. // if(tailPrev==-1)
    72. // {
    73. // tailPrev=obj->k;
    74. // }
    75. // return obj->a[tailPrev];
    76. return obj->a[(obj->tail-1+obj->k+1)%(obj->k+1)];
    77. }
    78. }
    79. bool myCircularQueueIsEmpty(MyCircularQueue* obj) {
    80. return obj->front==obj->tail;
    81. }
    82. bool myCircularQueueIsFull(MyCircularQueue* obj)
    83. {
    84. // int tailNext=obj->tail+1;
    85. // if(tailNext==obj->k+1)
    86. // {
    87. // tailNext=0;
    88. // }
    89. int tailNext=(obj->tail+1)%(obj->k+1);
    90. return obj->front==tailNext;
    91. // return obj->a[obj->tail+1];
    92. }
    93. void myCircularQueueFree(MyCircularQueue* obj) {
    94. free(obj->a);
    95. obj->tail=obj->front=0;
    96. obj->k=0;
    97. free(obj);
    98. }

    3.链式循环队列

    1. #define _CRT_SECURE_NO_WARNINGS 1
    2. #include
    3. #include
    4. #include;
    5. #include
    6. typedef struct ListNode
    7. {
    8. int val;
    9. struct ListNode* next;
    10. }ListNode;
    11. typedef struct MyCirQue
    12. {
    13. ListNode* front;
    14. ListNode* prev;
    15. ListNode* tail;
    16. int size;
    17. }MyCirQue;
    18. MyCirQue* MyCirQueInit(int k)
    19. {
    20. MyCirQue* ps = (MyCirQue*)malloc(sizeof(MyCirQue));
    21. ListNode* newnode = (ListNode*)malloc(sizeof(ListNode));
    22. newnode->next = NULL;
    23. ps->prev = NULL;
    24. ps->front = ps->tail = newnode;
    25. ps->size = 0;
    26. while (--k)
    27. {
    28. ListNode* newnode = (ListNode*)malloc(sizeof(ListNode));
    29. newnode->next = NULL;
    30. ps->tail->next = newnode;
    31. ps->tail = ps->tail->next;
    32. ps->size++;
    33. }
    34. ps->tail->next = ps->front;
    35. ps->tail = ps->front;
    36. }
    37. bool MyCirQueIsEmpty(MyCirQue* ps)
    38. {
    39. return ps->front == ps->tail;
    40. }
    41. bool MyCirQueIsFull(MyCirQue* ps)
    42. {
    43. return ps->tail->next == ps->front;
    44. }
    45. bool MyCirQuePush(MyCirQue* ps, int x)
    46. {
    47. if (MyCirQueIsFull(ps))
    48. {
    49. return false;
    50. }
    51. else
    52. {
    53. ps->tail->val = x;
    54. ps->prev = ps->tail;
    55. ps->tail = ps->tail->next;
    56. return true;
    57. }
    58. }
    59. bool MyCirQuePop(MyCirQue* ps)
    60. {
    61. if (MyCirQueIsEmpty(ps))
    62. {
    63. return false;
    64. }
    65. else
    66. {
    67. ps->front = ps->front->next;
    68. return true;
    69. }
    70. }
    71. int MyCirQueFront(MyCirQue* ps)
    72. {
    73. if (MyCirQueIsEmpty(ps))
    74. {
    75. return -100;
    76. }
    77. else
    78. {
    79. return ps->front->val;
    80. }
    81. }
    82. int MyCirQueTail(MyCirQue* ps)
    83. {
    84. if (MyCirQueIsEmpty(ps))
    85. {
    86. return -100;
    87. }
    88. else
    89. {
    90. return ps->prev->val;
    91. }
    92. }
    93. void MyCirQuePrint(MyCirQue* ps)
    94. {
    95. ListNode* cur = ps->front;
    96. while (cur != ps->tail)
    97. {
    98. printf("%d->", cur->val);
    99. cur = cur->next;
    100. }
    101. printf("NULL\n");
    102. }
    103. void SListDestory(MyCirQue* ps)
    104. {
    105. ListNode* cur = ps->front;
    106. while (ps->size--)
    107. {
    108. ListNode* next = cur->next;
    109. free(cur);
    110. cur = next;
    111. }
    112. }
    113. void MyCirQueDestory(MyCirQue* ps)
    114. {
    115. SListDestory(ps);
    116. free(ps);
    117. }
    118. int main()
    119. {
    120. MyCirQue* ps = MyCirQueInit(5);
    121. MyCirQuePush(ps, 1);
    122. MyCirQuePush(ps, 2);
    123. MyCirQuePush(ps, 3);
    124. MyCirQuePush(ps, 4);
    125. MyCirQuePop(ps);
    126. MyCirQuePrint(ps);
    127. MyCirQueDestory(ps);
    128. return 0;
    129. }

     

     4.一道妙的选择题

    • 题目:
      现有一顺序循环队列,其队头为front,队尾为rear,循环队列长度为N,最多存储N-1个数据。其队内有效长度为( B)
    • 内容:

      A.(rear - front + N) % N + 1

      B.(rear - front + N) % N

      C.(rear - front) % (N + 1)

      D.(rear - front + N) % (N - 1)

    • 答案:B

  • 相关阅读:
    传统 51 与STC-Y5内核 51 单片机对比&汇编指令
    前端页面变灰
    java ssm在线读书与分享论坛系统
    【NOI模拟赛】摆(线性代数,杜教筛)
    [附源码]java毕业设计学科类校外培训机构课程监管系统
    C++面试100问!(三)
    reportlab 生成pdf文件 (python)
    Cesium 常识——entity.position.getValue(viewer.clock.currentTime);
    DDS:domain
    问题解决系列:从源码讲解为什么是 ‘JZ0SL_ Unsupported SQL type 1111‘
  • 原文地址:https://blog.csdn.net/qq_64428099/article/details/126218658