当前位置:   article > 正文

【数据结构】队列的知识点_哪个数据结构不是用于实现队列的

哪个数据结构不是用于实现队列的

最近忙着写论文,好久没学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<stdio.h>
  3. #include<assert.h>
  4. #include<stdlib.h>
  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时,队列为满

举例:设计循环队列。

声明:本文内容由网友自发贡献,转载请注明出处:【wpsshop】
推荐阅读
相关标签
  

闽ICP备14008679号