当前位置:   article > 正文

数据结构——队列(C语言版)

数据结构——队列(C语言版)

前言:

在学习完数据结构顺序表和链表之后,其实我们就可以做很多事情了,后面的栈和队列,其实就是对前面的顺序表和链表的灵活运用,今天我们就来学习一下队列的原理和应用。

准备工作:本人习惯将文件放在test.c、SeqList.c、SeqList.h三个文件中来实现,其中test.c用来放主函数,SeqList.c用来放调用的函数,SeqList.h用来放头文件和函数声明

目录

什么是队列?

队列的节点结构

队列的基本操作

1、初始化

2、销毁

3、增加(插入数据)

4、删除

5、取队头、取队尾、取长度、判断头指针是否为空

完整的队列实例

总结


什么是队列?

队列中的数据是按照先进先出的顺序的,也就是说先进去的数字也先出来

因为队列的这种性质,所以队列我们用链表来实现比顺序表方便很多,因为用顺序表每插入一个数或者删除一个数都需要遍历整个数组,这样就会很容易出错且不够方便,我们一般采用单链表来实现队列

队列的节点结构

队列采用的单链表的结构,所以与单链表差异不大

  1. typedef int QDataType;
  2. typedef struct QueueNode
  3. {
  4. struct QueueNode* next;
  5. QDataType data;
  6. }QNode;

但是我们在操作中,因为队列是要先进先出,其实也就是尾部进数据,头部出数据,所以我们要定义一个头指针和一个尾指针指向头尾两个数据,这样有利于我们后面增加或者删除数据,我们可以再定义一个结构体来存放这两个指针

  1. typedef struct Queue
  2. {
  3. QNode* phead; //头指针
  4. QNode* ptail; //尾指针
  5. int size; //队列中的元素个数
  6. }Queue;

队列的基本操作

  1. //初始化
  2. void QueueInit(Queue* pq);
  3. //销毁
  4. void QueueDestroy(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. QDataType QueueSize(Queue* pq);
  15. //判断是否为空
  16. bool QueueEmpty(Queue* pq);

看上面的函数声明部分我们就可以看到我们每一步要实现的内容,接下来,我们就来一步一步进行实现

1、初始化

  1. //初始化
  2. void QueueInit(Queue* pq)
  3. {
  4. assert(pq);
  5. pq->phead = NULL;
  6. pq->ptail = NULL;
  7. pq->size = 0;
  8. }

参数全是一个结构体指针,而且肯定不能为空,所以我们下面的函数基本都要对pq进行断言

2、销毁

将头指针指向的空间逐个释放,最后把头指针和尾指针均赋为空指

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

3、增加(插入数据)

因为先进先出,实际上数据就是从尾部插入,从头部出去,即插入形式为尾插

  1. //插入
  2. void QueuePush(Queue* pq, QDataType x)
  3. {
  4. assert(pq);
  5. QNode* newnode = (QNode*)malloc(sizeof(QNode));
  6. newnode->data = x;
  7. newnode->next = NULL;
  8. //判断头部是否为空
  9. if (pq->phead == NULL)
  10. {
  11. pq->phead = pq->ptail = newnode;
  12. }
  13. else
  14. {
  15. pq->ptail->next = newnode;
  16. pq->ptail = newnode;
  17. }
  18. pq->size++;
  19. }

用单链表插入数据必须要考虑头部为空和不为空两种情况

4、删除

栈和队列都有一个特点就是,数据只会输出一遍,也就是数据一经输出就会销毁删除

如下:

1在输出之后就会被删除,删除的代码如下:

  1. //删除
  2. void QueuePop(Queue* pq)
  3. {
  4. assert(pq);
  5. assert(!QueueEmpty(pq));
  6. //1、一个节点
  7. //2、多个节点
  8. if (pq->phead->next == NULL)
  9. {
  10. free(pq->phead);
  11. pq->phead = pq->ptail = NULL;
  12. }
  13. else
  14. {
  15. QNode* ptr = pq->phead->next;
  16. free(pq->phead);
  17. pq->phead = ptr;
  18. }
  19. }

这里面又分为两种情况,难度不大,根据注释自行体会即可

5、取队头、取队尾、取长度、判断头指针是否为空

这几步难度不大,放在一起看看

取队头

  1. //取队头
  2. QDataType QueueFront(Queue* pq)
  3. {
  4. assert(pq);
  5. assert(!QueueEmpty(pq));
  6. return pq->phead->data;
  7. }

取队尾

  1. //取队尾
  2. QDataType QueueBack(Queue* pq)
  3. {
  4. assert(pq);
  5. assert(!QueueEmpty(pq));
  6. return pq->ptail->data;
  7. }

取长度

  1. //取长度
  2. QDataType QueueSize(Queue* pq)
  3. {
  4. assert(pq);
  5. return pq->size;
  6. }

判断头指针是否为空(这个函数应用上可以在下面的完整案列上体会一下)

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

完整的队列实例

test.c

  1. //队列
  2. void TestQNode()
  3. {
  4. Queue q;
  5. QueueInit(&q);
  6. QueuePush(&q, 1);
  7. QueuePush(&q, 2);
  8. QueuePush(&q, 3);
  9. QueuePush(&q, 4);
  10. printf("%d\n", QueueSize(&q));
  11. while (!QueueEmpty(&q))
  12. {
  13. printf("%d ", QueueFront(&q));
  14. QueuePop(&q);
  15. }
  16. QueueDestroy(&q);
  17. }
  18. int main()
  19. {
  20. TestQNode();
  21. return 0;
  22. }

SeqList.h

  1. //队列
  2. typedef int QDataType;
  3. typedef struct QueueNode
  4. {
  5. struct QueueNode* next;
  6. QDataType data;
  7. }QNode;
  8. typedef struct Queue
  9. {
  10. QNode* phead;
  11. QNode* ptail;
  12. int size;
  13. }Queue;
  14. //初始化
  15. void QueueInit(Queue* pq);
  16. //销毁
  17. void QueueDestroy(Queue* pq);
  18. //增加
  19. void QueuePush(Queue* pq,QDataType x);
  20. //删除
  21. void QueuePop(Queue* pq);
  22. //取队头
  23. QDataType QueueFront(Queue* pq);
  24. //取队尾
  25. QDataType QueueBack(Queue* pq);
  26. //取长度
  27. QDataType QueueSize(Queue* pq);
  28. //判断是否为空
  29. bool QueueEmpty(Queue* pq);

SeqList.c

  1. //初始化
  2. void QueueInit(Queue* pq)
  3. {
  4. assert(pq);
  5. pq->phead = NULL;
  6. pq->ptail = NULL;
  7. pq->size = 0;
  8. }
  9. //销毁
  10. void QueueDestroy(Queue* pq)
  11. {
  12. QNode* cur = pq->phead;
  13. while (cur)
  14. {
  15. QNode* next = cur->next;
  16. free(cur);
  17. cur = next;
  18. }
  19. pq->phead = pq->ptail = NULL;
  20. pq->size = 0;
  21. }
  22. //插入
  23. void QueuePush(Queue* pq, QDataType x)
  24. {
  25. assert(pq);
  26. QNode* newnode = (QNode*)malloc(sizeof(QNode));
  27. newnode->data = x;
  28. newnode->next = NULL;
  29. if (pq->phead == NULL)
  30. {
  31. pq->phead = pq->ptail = newnode;
  32. }
  33. else
  34. {
  35. pq->ptail->next = newnode;
  36. pq->ptail = newnode;
  37. }
  38. pq->size++;
  39. }
  40. //删除
  41. void QueuePop(Queue* pq)
  42. {
  43. assert(pq);
  44. assert(!QueueEmpty(pq));
  45. //1、一个节点
  46. //2、多个节点
  47. if (pq->phead->next == NULL)
  48. {
  49. free(pq->phead);
  50. pq->phead = pq->ptail = NULL;
  51. }
  52. else
  53. {
  54. QNode* ptr = pq->phead->next;
  55. free(pq->phead);
  56. pq->phead = ptr;
  57. }
  58. }
  59. //取队头
  60. QDataType QueueFront(Queue* pq)
  61. {
  62. assert(pq);
  63. assert(!QueueEmpty(pq));
  64. return pq->phead->data;
  65. }
  66. //取队尾
  67. QDataType QueueBack(Queue* pq)
  68. {
  69. assert(pq);
  70. assert(!QueueEmpty(pq));
  71. return pq->ptail->data;
  72. }
  73. //取长度
  74. QDataType QueueSize(Queue* pq)
  75. {
  76. assert(pq);
  77. return pq->size;
  78. }
  79. bool QueueEmpty(Queue* pq)
  80. {
  81. assert(pq);
  82. return pq->phead == NULL;
  83. }

运行后结果:

总结

总之,其实队列就是对链表的应用,熟练栈和队列,对我们巩固顺序表和链表帮助很大,当然,队列在一些场景下很实用,后面我会出一个专门的习题讲解篇章,讲数据结构的一些经典题型,感兴趣的可以点赞关注一下

创作不易,还请各位大佬点赞支持一下!!!

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

闽ICP备14008679号