当前位置:   article > 正文

数据结构——队列

数据结构——队列

目录

前言

一、队列

​编辑

二、队列的实现

2.1 队列结构

2.2 队列的初始化

2.4 入队列

2.5 出队列

2.6 获取队列尾部元素

2.7 获取队列头部元素

2.8 获取队列有效元素个数

2.9 判断队列是否为空

2.10 销毁队列

三、完整代码实现

总结


前言

之前我们了解到栈是一种特殊的线性表,现在我们来介绍另外一种特殊的线性表队列,队列是一种特殊的线性表,特殊之处在于它只允许在表的前端(front)进行删除操作,而在表的后端(rear)进行插入操作,和栈一样,队列是一种操作受限制的线性表。


一、队列

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

实际中我们有时还会使用一种队列叫循环队列。操作系统中生产者消费者模型 时可以就会使用循环队列。环形队列可以使用数组实现,也可以使用循环链表实现。

二、队列的实现

队列也可以数组和链表的结构实现,使用 链表 的结构实现更优一些,因为如果使用数组的结构,出队列在数组头上出数据,效率会比较低。
主要接口:
  1. typedef int QDataType;
  2. //队列节点
  3. typedef struct QueueNode {
  4. QDataType data;
  5. struct QueueNode* next;
  6. }QNode;
  7. //队列结构
  8. typedef struct Queue {
  9. QNode* phead;//头节点
  10. QNode* ptail;//尾节点
  11. int sz;
  12. }Queue;
  13. //初始化队列
  14. void QueueInit(Queue* pq);
  15. //入队列(队尾)
  16. void QueuePush(Queue* pq,QDataType x);
  17. //出队列(队头)
  18. void QueuePop(Queue* pq);
  19. //获取队列头部元素
  20. QDataType QueueFront(Queue* pq);
  21. //获取队列尾部元素
  22. QDataType QueueBack(Queue* pq);
  23. //获取队列有效元素个数
  24. int QueueSize(Queue* pq);
  25. //判断队列是否为空
  26. bool QueueEmpty(Queue* pq);
  27. //销毁队列
  28. void QueueDestroy(Queue* pq);

2.1 队列结构

由于我们用链表来实现队列,为了更好的完成队列操作,我们定义了一个结构体来表示队列的队头和队尾。

  1. //队列结构
  2. typedef struct Queue {
  3. QNode* phead;//头节点
  4. QNode* ptail;//尾节点
  5. int sz;
  6. }Queue;

2.2 队列的初始化

  1. void QueueInit(Queue* pq) {
  2. assert(pq);
  3. pq->phead = NULL;
  4. pq->ptail = NULL;
  5. pq->sz = 0;
  6. }

我们把队列的头和尾都置为空,队长置为零。

2.4 入队列

  1. void QueuePush(Queue* pq, QDataType x) {
  2. assert(pq);
  3. //创建新节点
  4. QNode* newNode = (QNode*)malloc(sizeof(QNode));
  5. if (newNode == NULL)
  6. {
  7. perror("malloc fail");
  8. }
  9. newNode->data = x;
  10. newNode->next = NULL;
  11. //从队尾插入
  12. if (pq->phead == NULL)
  13. {
  14. pq->phead = pq->ptail = newNode;
  15. }
  16. else
  17. {
  18. pq->ptail->next= newNode;
  19. pq->ptail = newNode;
  20. }
  21. //长度加一
  22. pq->sz++;
  23. }

我们先创建要插入的新的节点,然后从队列的队尾插入(即链表的尾插),最后队列长度加一。

2.5 出队列

  1. void QueuePop(Queue* pq) {
  2. assert(pq);
  3. assert(pq->phead != NULL);//队列不为空
  4. if (pq->phead == pq->ptail)
  5. {
  6. free(pq->ptail);
  7. pq->phead = pq->ptail = NULL;
  8. }
  9. else
  10. {
  11. QNode* next = pq->phead->next;;
  12. free(pq->phead);
  13. pq->phead = next;
  14. }
  15. pq->sz--;
  16. }

出队列从队头开始出去,但是我们这里需要分成两种情况讨论,第一种就是队列只有一个元素,我们要把头尾同时置为空,不然有野指针出现。第二种就是链表的头删操作。

2.6 获取队列尾部元素

  1. QDataType QueueBack(Queue* pq) {
  2. assert(pq);
  3. assert(pq->phead != NULL);
  4. return pq->ptail->data;
  5. }

我们先判断队列是否为空,然后直接返回尾部节点元素即可。

2.7 获取队列头部元素

  1. QDataType QueueFront(Queue* pq) {
  2. assert(pq);
  3. assert(pq->phead != NULL);
  4. return pq->phead->data;
  5. }

我们先判断队列是否为空,然后直接返回头部节点元素即可。

2.8 获取队列有效元素个数

  1. int QueueSize(Queue* pq) {
  2. assert(pq);
  3. return pq->sz;
  4. }
我们先判断队列是否为空,直接返回队列结构中的大小即可。

2.9 判断队列是否为空

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

直接返回,如果头节点等于空,即返回true,反之返回false。

2.10 销毁队列

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

和链表销毁差不多,我们要依次销毁每一个创建的节点。

三、完整代码实现

Queue.h
  1. #pragma once
  2. #define _CRT_SECURE_NO_WARNINGS 1
  3. #include<stdio.h>
  4. #include<assert.h>
  5. #include<stdbool.h>
  6. #include<stdlib.h>
  7. typedef int QDataType;
  8. //队列节点
  9. typedef struct QueueNode {
  10. QDataType data;
  11. struct QueueNode* next;
  12. }QNode;
  13. //队列结构
  14. typedef struct Queue {
  15. QNode* phead;//头节点
  16. QNode* ptail;//尾节点
  17. int sz;
  18. }Queue;
  19. //初始化队列
  20. void QueueInit(Queue* pq);
  21. //入队列(队尾)
  22. void QueuePush(Queue* pq,QDataType x);
  23. //出队列(队头)
  24. void QueuePop(Queue* pq);
  25. //获取队列头部元素
  26. QDataType QueueFront(Queue* pq);
  27. //获取队列尾部元素
  28. QDataType QueueBack(Queue* pq);
  29. //获取队列有效元素个数
  30. int QueueSize(Queue* pq);
  31. //判断队列是否为空
  32. bool QueueEmpty(Queue* pq);
  33. //销毁队列
  34. void QueueDestroy(Queue* pq);

Queue.c

  1. #include"Queue.h"
  2. //初始化队列
  3. void QueueInit(Queue* pq) {
  4. assert(pq);
  5. pq->phead = NULL;
  6. pq->ptail = NULL;
  7. pq->sz = 0;
  8. }
  9. //入队列(队尾)
  10. void QueuePush(Queue* pq, QDataType x) {
  11. assert(pq);
  12. //创建新节点
  13. QNode* newNode = (QNode*)malloc(sizeof(QNode));
  14. if (newNode == NULL)
  15. {
  16. perror("malloc fail");
  17. }
  18. newNode->data = x;
  19. newNode->next = NULL;
  20. if (pq->phead == NULL)
  21. {
  22. pq->phead = pq->ptail = newNode;
  23. }
  24. else
  25. {
  26. pq->ptail->next= newNode;
  27. pq->ptail = newNode;
  28. }
  29. //长度加一
  30. pq->sz++;
  31. }
  32. //出队列(队头)
  33. void QueuePop(Queue* pq) {
  34. assert(pq);
  35. assert(pq->phead != NULL);
  36. if (pq->phead == pq->ptail)
  37. {
  38. free(pq->ptail);
  39. pq->phead = pq->ptail = NULL;
  40. }
  41. else
  42. {
  43. QNode* next = pq->phead->next;;
  44. free(pq->phead);
  45. pq->phead = next;
  46. }
  47. pq->sz--;
  48. }
  49. //获取队列头部元素
  50. QDataType QueueFront(Queue* pq) {
  51. assert(pq);
  52. assert(pq->phead != NULL);
  53. return pq->phead->data;
  54. }
  55. //获取队列尾部元素
  56. QDataType QueueBack(Queue* pq) {
  57. assert(pq);
  58. assert(pq->phead != NULL);
  59. return pq->ptail->data;
  60. }
  61. //获取队列有效元素个数
  62. int QueueSize(Queue* pq) {
  63. assert(pq);
  64. return pq->sz;
  65. }
  66. //判断队列是否为空
  67. bool QueueEmpty(Queue* pq) {
  68. assert(pq);
  69. return pq->phead == NULL;
  70. }
  71. //销毁队列
  72. void QueueDestroy(Queue* pq) {
  73. assert(pq);
  74. QNode* cur = pq->phead;
  75. while (cur)
  76. {
  77. QNode* next =cur->next;
  78. free(cur);
  79. cur = next;
  80. }
  81. pq->phead = pq->ptail = NULL;
  82. pq->sz = 0;
  83. }

test.c


  1. #include"Queue.h"
  2. int main() {
  3. Queue pq;
  4. QueueInit(&pq);
  5. QueuePush(&pq, 1);
  6. QueuePush(&pq, 2);
  7. QueuePush(&pq, 3);
  8. int data = QueueFront(&pq);
  9. printf("%d ", data);
  10. QueuePop(&pq);
  11. QueuePush(&pq, 4);
  12. QueuePush(&pq, 5);
  13. while (!QueueEmpty(&pq)) {
  14. int data = QueueFront(&pq);
  15. printf("%d ", data);
  16. QueuePop(&pq);
  17. }
  18. QueueDestroy(&pq);
  19. }


总结

以上我们讲了队列一种特殊的线性表,讲了队列的概念和具体实现,希望对你有所帮助。

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

闽ICP备14008679号