• 数据结构:线性表之-队列


    目录

    什么是队列?

    详解:

    功能介绍

    代码实现

    定义队列基本结构

    1,初始化

    2, 销毁

    3,尾入数据

    4,头出数据

    5,取队头的数据

    6,取队尾的数据

    7,判断是否为空

    8,计算队列中的元素

    成品

    Queue.h

    Queue.c

    test.c


    队列的讲解将建立在有双向链表的基础之上进行讲解
    当然队列只是链表的一种分支
    单项链表详解:# 数据结构:线性表之-单向链表(无头)
    双向链表详解:# 数据结构:线性表之-循环双向链表(万字详解)

    什么是队列?


    队列是一种常见的数据结构,用于存储和管理数据的集合。它遵循先进先出(FIFO)的原则,即最先进入队列的元素最先被删除。类比一下,你可以把队列视为排队等待服务的人群,新来的人排在队列末尾,而需要服务的人从队列头部被依次处理。

    队列通常有两种基本操作:

    1. 入队(enqueue):将元素添加到队列的末尾。
    2. 出队(dequeue):从队列的头部删除一个元素,并返回被删除的元素。

    除了入队和出队操作,队列还可以支持其他操作,如获取队列的大小(元素个数)、判断队列是否为空等。队列在计算机科学中有广泛的应用,例如任务调度、缓冲区管理、计算机网络等领域。
    当队列已满时,新的元素无法入队,我们称之为队列满(Queue Full)。
    当队列为空时,没有元素可以出队,我们称之为队列空(Queue Empty)。

    队列的实现方式有多种,最常见的是使用数组或链表来存储元素。在数组实现中,我们使用一个固定大小的数组来存储元素,并使用两个指针(front和rear)分别指向队列的头部和尾部。入队操作时,将元素添加到rear指针所指位置,并将rear指针向后移动一位;出队操作时,将front指针所指位置的元素删除,并将front指针向后移动一位。

    队列的应用非常广泛。举例来说,在计算机的操作系统中,进程调度算法通常使用队列来管理待执行的进程。在网络数据传输中,数据包也会按照先后顺序排队等待传输。此外,实现广度优先搜索算法、缓冲区处理等也需要使用队列。队列数据结构的特性使得它在这些场景下非常实用,能够提高程序的效率和性能。

    详解:

    功能介绍

    1. //初始化
    2. void QueueInit(Queue* pq);
    3. //销毁
    4. void QueueDestory(Queue* pq);
    5. //尾入数据
    6. void QueuePush(Queue* pq, QDataType x);
    7. //头出数据
    8. void QueuePop(Queue* pq);
    9. //取队头的数据
    10. QDataType QueueFront(Queue* pq);
    11. //取队尾的数据
    12. QDataType QueueBack(Queue* pq);
    13. //判断是否为空
    14. bool QueueEmpty(Queue* pq);
    15. //计算队列中的元素
    16. int QueueSize(Queue* pq);

    代码实现

    定义队列基本结构

    1. typedef int QDataType;
    2. typedef struct QueueNode
    3. {
    4. struct QueueNode* next;
    5. QDataType data;
    6. }QNode;
    7. typedef struct Queue
    8. {
    9. //定义两个指针,tail方便尾插
    10. //方便对头出数据,尾入数据
    11. QNode* head;
    12. QNode* tail;
    13. }Queue;

    1,初始化

    1. void QueueInit(Queue* pq)
    2. {
    3. assert(pq);
    4. pq->head = pq->tail = NULL;
    5. }

    2, 销毁

    1. void QueueDestory(Queue* pq)
    2. {
    3. assert(pq);
    4. QNode* cur = pq->head;
    5. while (cur)
    6. {
    7. QNode* next = cur->next;
    8. free(cur);
    9. cur = next;
    10. }
    11. pq->head = pq->tail = NULL;
    12. }

    这段代码实现了队列的销毁操作。
    它接受一个指向队列的指针 pq,并通过遍历队列中的每个节点来逐个释放它们的内存。
    首先,它在 assert 语句中检查指针 pq 是否为空,以确保操作的安全性。
    然后,它将队列的头指针 pq->head 赋值给局部变量 cur,作为遍历的起始点。
    接下来使用一个循环来遍历队列的每个节点。在每次循环中,它首先将当前节点 cur 的下一个节点保存在指针变量 next 中,以便能够继续遍历队列。
    然后,它使用 free 函数释放当前节点 cur 的内存。
    最后,它将 cur 更新为 next,以便在下一次循环中继续遍历。在循环结束后,它将队列的头指针 pq->head 和尾指针 pq->tail 都设为 NULL,表示队列已经为空了。
    这段代码确保了在销毁队列后,所有节点的内存都得到了正确的释放,以避免内存泄漏。

    3,尾入数据

    1. void QueueDestory(Queue* pq)
    2. {
    3. assert(pq);
    4. //QNode* cur = pq->head;`:创建一个指针 `cur`,
    5. //并将其初始化为指向队列的头节点。这将是遍历队列的起点
    6. QNode* cur = pq->head;
    7. while (cur)
    8. {
    9. //创建一个指针 `next`,将其指向当前节点 `cur` 的下一个节点。
    10. //这是为了保留对下一个节点的引用,以便在释放当前节点后继续访问。
    11. QNode* next = cur->next;
    12. free(cur);
    13. cur = next;
    14. }
    15. //在循环结束后,将队列的头指针 `pq->head`
    16. //和尾指针 `pq->tail` 都设置为 NULL,表示队列为空。
    17. pq->head = pq->tail = NULL;
    18. }

    4,头出数据

    1. void QueuePop(Queue* pq)
    2. {
    3. assert(pq);
    4. assert(!QueueEmpty(pq));
    5. /*1,只有一个头节点
    6. 2,多个节点*/
    7. //判断队列是否只有一个节点。如果队列只有一个节点,即头节点,进入 `if` 语句。
    8. if (pq->head->next == NULL)
    9. {
    10. free(pq->head);
    11. pq->head = pq->tail = NULL;
    12. }
    13. else
    14. {
    15. //创建一个指针 `next`,将其指向头节点的下一个节点。
    16. QNode* next = pq->head->next;
    17. free(pq->head);
    18. //将指针 `pq->head` 更新为 `next`,即将头指针指向下一个节点。
    19. pq->head = next;
    20. }
    21. }

    5,取队头的数据

    1. QDataType QueueFront(Queue* pq)
    2. {
    3. assert(pq);
    4. assert(!QueueEmpty(pq));
    5. return pq->head->data;
    6. }

    6,取队尾的数据

    1. QDataType QueueBack(Queue* pq)
    2. {
    3. assert(pq);
    4. assert(!QueueEmpty(pq));
    5. return pq->tail->data;
    6. }

    7,判断是否为空

    1. bool QueueEmpty(Queue* pq)
    2. {
    3. assert(pq);
    4. return pq->head == NULL;
    5. }

    8,计算队列中的元素

    1. int QueueSize(Queue* pq)
    2. {
    3. assert(pq);
    4. QNode* cur = pq->head;
    5. int size = 0;
    6. while (cur)
    7. {
    8. ++size;
    9. cur = cur->next;
    10. }
    11. return size;
    12. }

    此处是单独创建一个函数进行计算队列中的元素个数
    另一种方法是在定义队列基本结构的结构体中定义一个int size
    每次尾增时++size
    每次头删时–size

    成品

    Queue.h

    1. #pragma once
    2. #include
    3. #include
    4. #include
    5. #include
    6. typedef int QDataType;
    7. typedef struct QueueNode
    8. {
    9. struct QueueNode* next;
    10. QDataType data;
    11. }QNode;
    12. typedef struct Queue
    13. {
    14. //定义两个指针,tail方便尾插
    15. //方便对头出数据,尾入数据
    16. QNode* head;
    17. QNode* tail;
    18. }Queue;
    19. //初始化
    20. void QueueInit(Queue* pq);
    21. //销毁
    22. void QueueDestory(Queue* pq);
    23. //尾入数据
    24. void QueuePush(Queue* pq, QDataType x);
    25. //头出数据
    26. void QueuePop(Queue* pq);
    27. //取队头的数据
    28. QDataType QueueFront(Queue* pq);
    29. //取队尾的数据
    30. QDataType QueueBack(Queue* pq);
    31. //判断是否为空
    32. bool QueueEmpty(Queue* pq);
    33. //计算队列中的元素
    34. int QueueSize(Queue* pq);

    Queue.c

    1. #include "Queue.h"
    2. //初始化
    3. void QueueInit(Queue* pq)
    4. {
    5. assert(pq);
    6. pq->head = pq->tail = NULL;
    7. }
    8. //销毁
    9. void QueueDestory(Queue* pq)
    10. {
    11. assert(pq);
    12. QNode* cur = pq->head;
    13. while (cur)
    14. {
    15. QNode* next = cur->next;
    16. free(cur);
    17. cur = next;
    18. }
    19. pq->head = pq->tail = NULL;
    20. }
    21. //尾入数据
    22. void QueuePush(Queue* pq, QDataType x)
    23. {
    24. assert(pq);
    25. QNode* newnode = (QNode*)malloc(sizeof(QNode));
    26. if (newnode == NULL)
    27. {
    28. printf("malloc fail\n");
    29. exit(-1);
    30. }
    31. newnode->data = x;
    32. newnode->next = NULL;
    33. if (pq->tail == NULL)
    34. {
    35. pq->head = pq->tail = newnode;
    36. }
    37. else
    38. {
    39. pq->tail->next = newnode;
    40. pq->tail = newnode;
    41. }
    42. }
    43. //头出数据
    44. void QueuePop(Queue* pq)
    45. {
    46. assert(pq);
    47. assert(!QueueEmpty(pq));
    48. //1,只有一个头节点
    49. //2,多个节点
    50. if (pq->head->next == NULL)
    51. {
    52. free(pq->head);
    53. pq->head = pq->tail = NULL;
    54. }
    55. else
    56. {
    57. QNode* next = pq->head->next;
    58. free(pq->head);
    59. pq->head = next;
    60. }
    61. }
    62. //取队头的数据
    63. QDataType QueueFront(Queue* pq)
    64. {
    65. assert(pq);
    66. assert(!QueueEmpty(pq));
    67. return pq->head->data;
    68. }
    69. //取队尾的数据
    70. QDataType QueueBack(Queue* pq)
    71. {
    72. assert(pq);
    73. assert(!QueueEmpty(pq));
    74. return pq->tail->data;
    75. }
    76. //判断是否为空
    77. bool QueueEmpty(Queue* pq)
    78. {
    79. assert(pq);
    80. return pq->head == NULL;
    81. }
    82. //计算队列中的元素
    83. int QueueSize(Queue* pq)
    84. {
    85. assert(pq);
    86. QNode* cur = pq->head;
    87. int size = 0;
    88. while (cur)
    89. {
    90. ++size;
    91. cur = cur->next;
    92. }
    93. return size;
    94. }

    test.c

    test.c只是用于测试代码,菜单的写法本文将不进行讲解。
    但test.c中含有对查找and销毁and存储链元素个数的使用方法进行了示例可以当参考。

    1. #include "Queue.h"
    2. void test()
    3. {
    4. Queue q;
    5. QueueInit(&q);
    6. QueuePush(&q, 1);
    7. QueuePush(&q, 2);
    8. QueuePush(&q, 3);
    9. QueuePush(&q, 4);
    10. while (!QueueEmpty(&q))
    11. {
    12. printf("%d ", QueueFront(&q));
    13. QueuePop(&q);
    14. }
    15. printf("\n");
    16. QueueDestory(&q);
    17. }
    18. int main()
    19. {
    20. test();
    21. return 0;
    22. }
  • 相关阅读:
    mac媲美PS的修图软件:Pixelmator Pro Mac 中文激活版
    Linux从入门到精通(十一)——计划任务
    Load-balanced-online-OJ-system 负载均衡的OJ系统项目
    Java读写文件时的GBK和UTF8转换问题
    linux系统---防火墙
    C语言static关键字
    大学生个人网站作业 超简单DIV CSS个人网页成品 简单个人网站作业模板 HTML个人网页设计下载 简约黑白色个人主页
    一起Talk Android吧(第三百六十八回:多线程之精准唤醒)
    安卓面试总结(4)——Java 多线程II
    『PyQt5-Qt Designer篇』| 13 Qt Designer中如何给工具添加菜单和工具栏?
  • 原文地址:https://blog.csdn.net/2301_77649794/article/details/133151224