当前位置:   article > 正文

双端队列(C语言实现)_c语言双端队列

c语言双端队列

队列是一种操作受限的线性表,它只允许从队头出队,从队尾入队,就像生活中的排队一样。双端队列放宽了这种限制,它可以从队头出队或入队,也可以从队尾出队或入队。

一般队列:

 

双端队列:

 

双端队列可以从两端进行出队和入队,也可以对一种操作进行限制,例如,入队受限(一端入队)的双端队列和出队(一端出队)的双端队列。

双端队列可以使用循环数组来实现,也可以使用双链表来实现,下面给出双端队列的循环数组实现,链表实现的原理与队列的实现也是类似的,但由于双端队列可能会从尾部删除结点,所以为了效率,使用能够找到前驱结点的双链表。

循环数组实现:

  1. #define MAX_SIZE 20
  2. //双端队列可以使用数组或链表实现,使用双链表应该比较简单,但这里使用循环数组来实现双端队列的增删改查等操作
  3. typedef struct DoubleQueue {
  4. int front;//头指针
  5. int rear;//尾指针
  6. int numofele;//队列中的元素数量
  7. int arr[MAX_SIZE];//假设队列中只存储非负整数,最大容量为MAX_SIZE
  8. }DoubleQueue;
  9. //创建队列
  10. DoubleQueue* CreatQueue() {
  11. DoubleQueue* q = (DoubleQueue*)malloc(sizeof(DoubleQueue));
  12. if (q == NULL) {
  13. perror("malloc");
  14. return NULL;
  15. }
  16. //假设队列的队头入队和队尾入队都是从数组下标为0处开始
  17. q->front = q->rear = -1;
  18. q->numofele = 0;
  19. return q;
  20. }
  21. //清空队列
  22. void ClearQueue(DoubleQueue* q) {
  23. if (q == NULL) {
  24. printf("队列不存在\n");
  25. return;
  26. }
  27. //清空队列时,只需要改变头尾指针和队列中元素的数量即可
  28. q->front = q->rear = -1;
  29. q->numofele = 0;
  30. }
  31. //销毁队列
  32. void DestoryQueue(DoubleQueue* q) {
  33. if (q == NULL) {
  34. printf("队列不存在\n");
  35. return;
  36. }
  37. //由于队列只使用了一次动态内存分配,所以直接free
  38. free(q);
  39. q = NULL;
  40. }
  41. //判断队列是否为空
  42. bool IsEmpty(DoubleQueue* q) {
  43. if (q == NULL) {
  44. printf("队列不存在\n");
  45. return true;//返回true为了防止在队列为空时的操作引用空指针
  46. }
  47. return q->numofele == 0;
  48. }
  49. //判断队列是否为满
  50. bool IsFull(DoubleQueue* q) {
  51. if (q == NULL) {
  52. printf("队列不存在\n");
  53. return true;//为了防止在队列不满情况下对空指针的操作
  54. }
  55. return q->numofele == MAX_SIZE;
  56. }
  57. //返回队头元素
  58. int GetHead(DoubleQueue* q) {
  59. if (q == NULL) {
  60. printf("队列不存在\n");
  61. return -1;//假设队列中存储非负整数,返回-1表示错误
  62. }
  63. if (IsEmpty(q)) {
  64. printf("队列为空,不存在队头元素\n");
  65. return -1;
  66. }
  67. return q->arr[q->front];
  68. }
  69. //返回队尾元素
  70. int GetTail(DoubleQueue* q) {
  71. if (q == NULL) {
  72. printf("队列不存在\n");
  73. return -1;//假设队列中存储非负整数,返回-1表示错误
  74. }
  75. if (IsEmpty(q)) {
  76. printf("队列为空,不存在队尾元素\n");
  77. return -1;
  78. }
  79. return q->arr[q->rear];
  80. }
  81. //获得从队头入队的下标
  82. int GetHeadIndex(DoubleQueue* q, int size) {
  83. if (IsEmpty(q)) {
  84. q->rear = 0;//如果从对头入队的是第一个元素,则需要将队头队尾指针都设为0
  85. return 0;
  86. }
  87. if (q->front - 1 < 0) {
  88. return (q->front - 1) + size;
  89. }
  90. else {
  91. return q->front - 1;
  92. }
  93. }
  94. //从队头入队
  95. void EnqueueFromHead(DoubleQueue* q, int k) {
  96. if (q == NULL) {
  97. printf("队列不存在\n");
  98. return;
  99. }
  100. if (IsFull(q)) {
  101. printf("队列已满,无法入队\n");
  102. return;
  103. }
  104. q->front = GetHeadIndex(q, MAX_SIZE);
  105. q->numofele++;
  106. q->arr[q->front] = k;
  107. }
  108. //得到从队尾入队的下标
  109. int GetTailIndex(DoubleQueue* q, int size) {
  110. if (IsEmpty(q)) {
  111. q->front = 0;
  112. return 0;
  113. }
  114. return (q->rear + 1) % size;
  115. }
  116. //从队尾入队
  117. void EnqueueFromTail(DoubleQueue* q, int k) {
  118. if (q == NULL) {
  119. printf("队列不存在\n");
  120. return;
  121. }
  122. if (IsFull(q)) {
  123. printf("队列已满,无法入队\n");
  124. return;
  125. }
  126. q->rear = GetTailIndex(q, MAX_SIZE);
  127. q->numofele++;
  128. q->arr[q->rear] = k;
  129. }
  130. //从队头出队
  131. int DequeueFromHead(DoubleQueue* q) {
  132. if (q == NULL) {
  133. printf("队列不存在\n");
  134. return -1;
  135. }
  136. if (IsEmpty(q)) {
  137. printf("队列为空,无法出队\n");
  138. return -1;
  139. }
  140. q->numofele--;
  141. int ret = q->arr[q->front];
  142. q->front = (q->front + 1) % MAX_SIZE;
  143. return ret;
  144. }
  145. //从队尾出队
  146. int DequeueFromTail(DoubleQueue* q) {
  147. if (q == NULL) {
  148. printf("队列不存在\n");
  149. return -1;
  150. }
  151. if (IsEmpty(q)) {
  152. printf("队列为空,无法出队\n");
  153. return -1;
  154. }
  155. int ret = q->arr[q->rear];
  156. q->numofele--;
  157. if (q->rear - 1 < 0) {
  158. q->rear = q->rear - 1 + MAX_SIZE;
  159. }
  160. else {
  161. q->rear = q->rear - 1;
  162. }
  163. return ret;
  164. }
  165. //从队头开始打印队列数据
  166. void Print(DoubleQueue* q) {
  167. if (q == NULL) {
  168. printf("队列不存在\n");
  169. return;
  170. }
  171. if (IsEmpty(q)) {
  172. printf("队列为空,无法打印\n");
  173. return;
  174. }
  175. int count = q->numofele;
  176. int p = q->front;
  177. while (count--) {
  178. printf("%d ", q->arr[p]);
  179. p = (p + 1) % MAX_SIZE;
  180. }
  181. printf("\n--------------------------\n");
  182. }

测试代码:

  1. #include <stdio.h>
  2. #include <stdbool.h>
  3. #include <stdlib.h>
  4. int main() {
  5. DoubleQueue* q = CreatQueue();
  6. //从队头入队10个元素
  7. for (int i = 0; i < 10; i++) {
  8. EnqueueFromHead(q, i);
  9. }
  10. Print(q);
  11. for (int i = 10; i < 20; i++) {
  12. EnqueueFromTail(q, i);
  13. }
  14. Print(q);
  15. printf("从队头删除的元素是 %d\n", DequeueFromHead(q));
  16. Print(q);
  17. printf("从队尾删除的元素是:%d\n", DequeueFromTail(q));
  18. Print(q);
  19. printf("队头元素是:%d\n", GetHead(q));
  20. printf("队尾元素是:%d\n", GetTail(q));
  21. return 0;
  22. }

 

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

闽ICP备14008679号