当前位置:   article > 正文

数据结构——队列_链队列判断只有一个元素

链队列判断只有一个元素

一、定义

队列:只允许在一端进行插入数据操作,在另一端进行删除数据操作的特殊线性表,队列具有先进先出的特性。

队尾:进行插入操作的一端。

队头:进行删除操作的一端。

二、结构体定义

  1. // 链式结构:表示队列
  2. typedef int QDataType;
  3. typedef struct QListNode
  4. {
  5. struct QListNode* next;
  6. QDataType data;
  7. }QNode;
  8. // 队列的结构
  9. typedef struct Queue
  10. {
  11. QNode* front;//队头
  12. QNode* rear;//队尾
  13. }Queue;

若采用顺序表的方式实现队列,随着出队入队的操作,队头指针和队尾指针的移动,队头前的空间就可能发生内存泄漏,或出现假溢出问题。对此有两种解决方法,一种是采用链表的方式实现队列,一种是采用循环队列,这里采用的是链表的方式实现队列,随后会发布循环队列的实现方法。

三、接口实现

  1. void Queue_Tese();//队列功能测试函数
  2. QNode* buyQNode(QDataType data);//带头结点的单链表
  3. void QueueInit(Queue* q);// 初始化队列
  4. void QueuePush(Queue* q, QDataType data);// 队尾入队列
  5. void QueuePop(Queue* q);// 队头出队列
  6. QDataType QueueFront(Queue* q);// 获取队列头部元素
  7. QDataType QueueBack(Queue* q);// 获取队列队尾元素
  8. int QueueSize(Queue* q);// 获取队列中有效元素个数
  9. int QueueEmpty(Queue* q);// 检测队列是否为空,为空返回1,非空返回0
  10. void QueueDestroy(Queue* q);// 销毁队列

1.创建带头结点的单链表

  1. QNode* buyQNode(QDataType data) {//带头结点的单链表
  2. QNode* newNode = (QNode*)malloc(sizeof(QNode));
  3. if (newNode == NULL) {
  4. assert(0);
  5. return NULL;
  6. }
  7. newNode->data = data;
  8. newNode->next = NULL;
  9. return newNode;
  10. }

使用带头结点的单链表实现队列,可以简化实现过程的很多操作。

2.初始化队列

  1. void QueueInit(Queue* q) {// 初始化队列
  2. assert(q);
  3. q->front = buyQNode(0);
  4. q->rear = q->front;
  5. }

将队列头尾指针都指向头结点即可。

3.入队

  1. void QueuePush(Queue* q, QDataType data) {// 队尾入队列
  2. assert(q);
  3. QNode* newNode = buyQNode(data);
  4. q->rear->next = newNode;
  5. q->rear = newNode;
  6. }

只能在队尾入队。

4.判空

  1. int QueueEmpty(Queue* q) {// 检测队列是否为空,为空返回1,非空返回0
  2. assert(q);
  3. return q->front == q->rear;
  4. }

队头队尾指针都在初始位置指向头结点,即队列为空,若用顺序表实现则是队头队尾都在0号位置即队列为空。

5.出队

  1. void QueuePop(Queue* q){// 队头出队列
  2. assert(q);
  3. if (QueueEmpty(q)) {//判空
  4. return;
  5. }
  6. QNode* delNode = q->front->next;
  7. q->front->next = delNode->next;
  8. if (delNode == q->rear) {//若队列只有一个元素,出队列后要将队尾放到头结点处
  9. q->rear = q->front;
  10. }
  11. free(delNode);
  12. }

出队列只能在队头出队。因为这里采用的是带头结点的单链表实现队列,所以在队列只有一个元素时出队列,需要把队尾指针放回到头节处。

6.获取队头

  1. QDataType QueueFront(Queue* q) {// 获取队列头部元素
  2. assert(q);
  3. return q->front->next->data;
  4. }

7.获取队尾

  1. QDataType QueueBack(Queue* q) {// 获取队列队尾元素
  2. assert(q);
  3. return q->rear->data;
  4. }

8.获取队列中有效元素个数

  1. int QueueSize(Queue* q) {// 获取队列中有效元素个数
  2. assert(q);
  3. QNode* cur = q->front->next;
  4. int len = 0;
  5. while (cur) {
  6. len++;
  7. cur = cur->next;
  8. }
  9. return len;
  10. }

通过单链表的遍历计数实现。

9.队列销毁

  1. void QueueDestroy(Queue* q) {// 销毁队列
  2. assert(q);
  3. QNode* cur = q->front->next;
  4. while (cur) {
  5. q->front->next = cur->next;
  6. free(cur);
  7. cur = q->front->next;
  8. }
  9. free(q->front);
  10. q->front = q->rear = NULL;
  11. }

循环释放每个结点,最后置空头尾指针。

四、接口测试

1.测试用例

  1. void Queue_Tese() {//队列功能测试函数
  2. Queue q;
  3. QueueInit(&q);
  4. printf("size = %d\n", QueueSize(&q));
  5. // 入队列
  6. QueuePush(&q, 1);
  7. QueuePush(&q, 2);
  8. QueuePush(&q, 3);
  9. QueuePush(&q, 4);
  10. QueuePush(&q, 5);
  11. QueuePush(&q, 6);
  12. QueuePush(&q, 7);
  13. printf("\nsize = %d\n", QueueSize(&q));
  14. printf("front = %d\n", QueueFront(&q));
  15. printf("back = %d\n", QueueBack(&q));
  16. // 出队列
  17. QueuePop(&q);
  18. printf("\nsize = %d\n", QueueSize(&q));
  19. printf("front = %d\n", QueueFront(&q));
  20. printf("back = %d\n", QueueBack(&q));
  21. QueuePop(&q);
  22. QueuePop(&q);
  23. QueuePop(&q);
  24. QueuePop(&q);
  25. QueuePop(&q);
  26. printf("\nsize = %d\n", QueueSize(&q));
  27. printf("front = %d\n", QueueFront(&q));
  28. printf("back = %d\n", QueueBack(&q));
  29. QueuePop(&q);
  30. QueuePop(&q);
  31. printf("\nsize = %d\n", QueueSize(&q));
  32. QueueDestroy(&q);
  33. }

2.测试结果

五、完整代码

  1. #include<stdio.h>
  2. #include<assert.h>
  3. #include<malloc.h>
  4. // 链式结构:表示队列
  5. typedef int QDataType;
  6. typedef struct QListNode
  7. {
  8. struct QListNode* next;
  9. QDataType data;
  10. }QNode;
  11. // 队列的结构
  12. typedef struct Queue
  13. {
  14. QNode* front;//队头
  15. QNode* rear;//队尾
  16. }Queue;
  17. void Queue_Tese();//队列功能测试函数
  18. QNode* buyQNode(QDataType data);//带头结点的单链表
  19. void QueueInit(Queue* q);// 初始化队列
  20. void QueuePush(Queue* q, QDataType data);// 队尾入队列
  21. void QueuePop(Queue* q);// 队头出队列
  22. QDataType QueueFront(Queue* q);// 获取队列头部元素
  23. QDataType QueueBack(Queue* q);// 获取队列队尾元素
  24. int QueueSize(Queue* q);// 获取队列中有效元素个数
  25. int QueueEmpty(Queue* q);// 检测队列是否为空,为空返回1,非空返回0
  26. void QueueDestroy(Queue* q);// 销毁队列
  27. int main() {
  28. Queue_Tese();
  29. return 0;
  30. }
  31. QNode* buyQNode(QDataType data) {//带头结点的单链表
  32. QNode* newNode = (QNode*)malloc(sizeof(QNode));
  33. if (newNode == NULL) {
  34. assert(0);
  35. return NULL;
  36. }
  37. newNode->data = data;
  38. newNode->next = NULL;
  39. return newNode;
  40. }
  41. void QueueInit(Queue* q) {// 初始化队列
  42. assert(q);
  43. q->front = buyQNode(0);
  44. q->rear = q->front;
  45. }
  46. void QueuePush(Queue* q, QDataType data) {// 队尾入队列
  47. assert(q);
  48. QNode* newNode = buyQNode(data);
  49. q->rear->next = newNode;
  50. q->rear = newNode;
  51. }
  52. int QueueEmpty(Queue* q) {// 检测队列是否为空,为空返回1,非空返回0
  53. assert(q);
  54. return q->front == q->rear;
  55. }
  56. void QueuePop(Queue* q){// 队头出队列
  57. assert(q);
  58. if (QueueEmpty(q)) {//判空
  59. return;
  60. }
  61. QNode* delNode = q->front->next;
  62. q->front->next = delNode->next;
  63. if (delNode == q->rear) {//若队列只有一个元素,出队列后要将队尾放到头结点处
  64. q->rear = q->front;
  65. }
  66. free(delNode);
  67. }
  68. QDataType QueueFront(Queue* q) {// 获取队列头部元素
  69. assert(q);
  70. return q->front->next->data;
  71. }
  72. QDataType QueueBack(Queue* q) {// 获取队列队尾元素
  73. assert(q);
  74. return q->rear->data;
  75. }
  76. int QueueSize(Queue* q) {// 获取队列中有效元素个数
  77. assert(q);
  78. QNode* cur = q->front->next;
  79. int len = 0;
  80. while (cur) {
  81. len++;
  82. cur = cur->next;
  83. }
  84. return len;
  85. }
  86. void QueueDestroy(Queue* q) {// 销毁队列
  87. assert(q);
  88. QNode* cur = q->front->next;
  89. while (cur) {
  90. q->front->next = cur->next;
  91. free(cur);
  92. cur = q->front->next;
  93. }
  94. free(q->front);
  95. q->front = q->rear = NULL;
  96. }
  97. void Queue_Tese() {//队列功能测试函数
  98. Queue q;
  99. QueueInit(&q);
  100. printf("size = %d\n", QueueSize(&q));
  101. // 入队列
  102. QueuePush(&q, 1);
  103. QueuePush(&q, 2);
  104. QueuePush(&q, 3);
  105. QueuePush(&q, 4);
  106. QueuePush(&q, 5);
  107. QueuePush(&q, 6);
  108. QueuePush(&q, 7);
  109. printf("\nsize = %d\n", QueueSize(&q));
  110. printf("front = %d\n", QueueFront(&q));
  111. printf("back = %d\n", QueueBack(&q));
  112. // 出队列
  113. QueuePop(&q);
  114. printf("\nsize = %d\n", QueueSize(&q));
  115. printf("front = %d\n", QueueFront(&q));
  116. printf("back = %d\n", QueueBack(&q));
  117. QueuePop(&q);
  118. QueuePop(&q);
  119. QueuePop(&q);
  120. QueuePop(&q);
  121. QueuePop(&q);
  122. printf("\nsize = %d\n", QueueSize(&q));
  123. printf("front = %d\n", QueueFront(&q));
  124. printf("back = %d\n", QueueBack(&q));
  125. QueuePop(&q);
  126. QueuePop(&q);
  127. printf("\nsize = %d\n", QueueSize(&q));
  128. QueueDestroy(&q);
  129. }

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

闽ICP备14008679号