• 【数据结构】队列的知识点


    最近忙着写论文,好久没学C++,学习放松一下……

    目录

    队列

    1.队列的概念及结构

    2.模拟实现

    3.队列常见操作(全代码实现)

    4、队列的应用

    leetcode 232 用栈实现队列

    leetcode 225 用队列实现栈

    假溢出

    真溢出

    5、循环队列


    队列

    1.队列的概念及结构

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

    2.模拟实现

       队列存储数据-》有空间来存储数据--》空间的结构:连续或链式结构

    队列:

    尾部进行数据的插入

    头部进行数据的删除

    对于队列来说:采用顺序结构来实现尾插还行,但是头删时间复杂度为O(N).

    用链表来说:

    所以用链表实现队列更方便

    3.队列常见操作(全代码实现)

     常见操作如下

    头文件

    1. #pragma once
    2. typedef int DataType;
    3. // 队列中底层链表中的节点的结构
    4. typedef struct QNode
    5. {
    6. struct QNode* next;
    7. DataType data;
    8. }QNode;
    9. // 队列的结构
    10. typedef struct Queue
    11. {
    12. QNode* front; // 指向队头
    13. QNode* back; // 指向队尾
    14. }Queue;
    15. void QueueInit(Queue* q); //队列结构初始化
    16. void QueuePush(Queue* q, DataType data); //队尾插入数据
    17. void QueuePop(Queue* q);
    18. int QueueSize(Queue* q); //队列有多少元素
    19. int QueueEmpty(Queue* q);
    20. DataType QueueBack(Queue* q); //获得队尾元素
    21. DataType QueueFront(Queue* q); //获得队头元素
    22. void QueueDestroy(Queue* q);
    23. // 测试队列
    24. void TestQueue();

    函数功能的实现

    1. #include"queue.h"
    2. #include
    3. #include
    4. #include
    5. //实现队列时采用不带头结点的单链表
    6. void QueueInit(Queue* q)
    7. {
    8. assert(q);
    9. q->back = NULL;
    10. q->front = NULL;
    11. }
    12. QNode* BuyQNode(DataType data) //创建结点
    13. {
    14. QNode* newNode = (QNode*)malloc(sizeof(QNode));
    15. if (NULL == newNode)
    16. {
    17. assert(0);
    18. return NULL;
    19. }
    20. newNode->data = data;
    21. newNode->next = NULL;
    22. return newNode;
    23. }
    24. void QueuePush(Queue* q, DataType data)//队尾插入数据 ;O(1)
    25. {
    26. assert(q);
    27. QNode* newNode = BuyQNode(data);//创建结点进行尾插
    28. //队列为空:即链表为空; 头尾都指向这个点
    29. if (QueueEmpty(q))
    30. {
    31. q->front = newNode;
    32. q->back = newNode;
    33. }
    34. else //队列不空,链表有节点
    35. {
    36. q->back->next = newNode;//给Back后插入结点
    37. q->back = newNode; //新的back为刚插入的点
    38. }
    39. return q;
    40. }
    41. void QueuePop(Queue* q) //头删
    42. {
    43. assert(q);
    44. if (QueueEmpty(q)) //空链表
    45. {
    46. return;
    47. }
    48. else if(q->back == q->front)//只有一个结点
    49. {
    50. free(q->back);
    51. q->back = NULL;
    52. q->front = NULL;
    53. }
    54. else
    55. {
    56. QNode* delNode = q->front;//要删除的结点保存
    57. q->front = delNode->next;
    58. free(delNode);
    59. }
    60. }
    61. int QueueSize(Queue* q) //队列有多少元素
    62. {
    63. assert(q);
    64. QNode* cur = q->front;
    65. int count = 0;
    66. while (cur)
    67. {
    68. count++;
    69. cur = cur->next;
    70. }
    71. return count;
    72. }
    73. int QueueEmpty(Queue* q)
    74. {
    75. assert(q);
    76. return NULL == q->front;
    77. }
    78. DataType QueueBack(Queue* q) //获得队尾元素
    79. {
    80. assert(q);
    81. return q->back->data;
    82. }
    83. DataType QueueFront(Queue* q) //获得队头元素
    84. {
    85. assert(q);
    86. return q->front->data;
    87. }
    88. void QueueDestroy(Queue* q)
    89. {
    90. QNode* cur = q->front;
    91. while (cur)
    92. {
    93. q->front = cur->next;
    94. free(cur);
    95. cur = q->front;
    96. }
    97. //删完了是空队列,所以指向置为空
    98. q->front = NULL;
    99. q->back = NULL;
    100. }
    101. // 测试队列
    102. void TestQueue()
    103. {
    104. Queue q;
    105. QueueInit(&q); //初始化队列
    106. QueuePush(&q, 1);
    107. QueuePush(&q, 2);
    108. QueuePush(&q, 3);
    109. QueuePush(&q, 4);
    110. QueuePush(&q, 5);
    111. QueuePush(&q, 6);
    112. printf("size= %d\n", QueueSize(&q));
    113. printf("front=%d\n", QueueFront(&q));
    114. printf("back=%d\n", QueueBack(&q));
    115. QueuePop(&q);
    116. QueuePop(&q);
    117. printf("size= %d\n", QueueSize(&q));
    118. printf("front=%d\n", QueueFront(&q));
    119. printf("back=%d\n", QueueBack(&q));
    120. QueueDestroy(&q);
    121. }

    最后放在主函数中执行,输入自己想测试的功能,代码无误

    1. #include"Queue.h"
    2. int main()
    3. {
    4. TestQueue();
    5. return 0;
    6. }

    4、队列的应用

    以下 ( ) 不是队列的基本运算?  B
    A 从队尾插入一个新元素
    B 从队列中删除第 i 个元素
    C 判断一个队列是否为空
    D 读取队头元素的值
    //只能队尾插入队头删除

    leetcode 232 用栈实现队列

    leetcode 225 用队列实现栈

    假溢出

     出队列时为了达到0(1)的效率,每次让front往后移动

    带来的问题:假溢出

    在入队列的时候,back一直往后移动,当back移动到空间末尾的时候,认为队列已经满了,但是由于出队列是让front往后移动的,因此当back在空间末尾的时侯,空间起始位置如果有空余位置,这种情况称为顺序方式实现队列假溢出问题。

    即:当队尾back在空间末尾的时候,队列中有效元素并没有将空间真正存储满

    真溢出

     队列中有效元素已经彻底将空间填充满了,后续还需要继续入队列

    一直在入队列,没有出队列

    因此,顺序结构不适合用来实现队列

    5、循环队列

    为了解决顺序队列中存在的假溢出问题,提出循环队列

     当front == rear ,为空队列

    问题:当front == rear 时,无法区分队列是空是满

    解决方法:

    法1.少用一个存储空间,如图(b)

    (rear + 1) % N == front    N是空间容量 

    法2.使用一个标记: flag,初始值设置为0

    每次入队时,flag置为1,出队列为0

    队列满的时候: front == rear && flag == 1

    法3:使用计数count

    入队列时count++ ,出队列时count--;

    空队列时count为0 ;当count == N时,队列为满

    举例:设计循环队列。

  • 相关阅读:
    多表数据增量导入详细文档
    基于mysql关系型数据库实现分布式锁以及存在的问题
    【电商运营】教你这几招,告别无效预设回复
    Vmware+UOS-server-1050e虚拟机安装(含软件链接)
    java农家乐旅游管理系统springboot+vue
    python如何读写excel
    系统架构设计:11 论湖仓一体架构及其应用
    第四章 将对象映射到 XML - 异常
    [云原生] K8s之pod进阶
    【Serverless】Unity快速集成认证服务实现邮件登录
  • 原文地址:https://blog.csdn.net/weixin_59215611/article/details/127035440