当前位置:   article > 正文

队列的链式存储结构及实现_队列的链式存储结构的实现

队列的链式存储结构的实现

队列的链式存储结构,其实就是线性表的单链表,只不过它只是尾进头出而已,我们把它简称为链队列为了操作上的方便,我们将队头指针指向链队列的头结点,而队尾指针指向终端节点。如果



空队列时,front和rear都指向头结点。



入队操作:

在队尾添加元素,先将队尾元素的next指向添加的元素,然后将队尾指针重新指向新的队尾即可。


出队操作:

头结结点指向的结点即为队头结点,出队操作,就是把队头结点干掉,先把头结点指向新的队头结点(也就是旧的队头结点的后继结点),然后释放旧的队头结点。 如果链表除头结点外只剩一个元素时,则需将rear指向头结点即可


下面是队列链式存储结构实现的具体代码:

  1. #define _CRT_SECURE_NO_WARNINGS
  2. #include <stdio.h>
  3. #include <string.h>
  4. #include <math.h>
  5. #include <stdlib.h>
  6. #define QUEUESIZE 10
  7. #define ERROR 0
  8. #define OK 1
  9. #define TRUE 1
  10. #define FALSE 0
  11. #define EleType int
  12. #define Status int
  13. //链队列结点
  14. typedef struct QueueNode
  15. {
  16. EleType e;//数据域
  17. struct QueueNode* next;//指针域
  18. }QueueNode,*LinkQueuePoi;
  19. typedef struct LinkQueue
  20. {
  21. LinkQueuePoi front;//指向头结点
  22. LinkQueuePoi rear;//指向队尾
  23. }LinkQueue;
  24. /*
  25. 初始化链队列
  26. 链队列为空时,链队列队头指针队尾指针均指向头结点
  27. */
  28. Status InitLinkQueue(LinkQueue* queue)
  29. {
  30. //空指针
  31. if (!queue)
  32. {
  33. return ERROR;
  34. }
  35. QueueNode* node = (QueueNode*)malloc(sizeof(QueueNode));//头结点
  36. node->next = NULL;
  37. queue->front = queue->rear = node;
  38. return OK;
  39. }
  40. /*
  41. 清空链队列
  42. 将所有元素释放
  43. */
  44. Status CleaerLinkQueue(LinkQueue* queue)
  45. {
  46. //空指针
  47. if (!queue)
  48. {
  49. return ERROR;
  50. }
  51. //空链队列
  52. if (queue->front == queue->rear)
  53. {
  54. return ERROR;
  55. }
  56. QueueNode* node = queue->front->next;//队头元素
  57. while (node)
  58. {
  59. queue->front->next = node->next;//指向新的队头结点
  60. if (queue->rear == node)//当删除的是队尾元素时,将队尾指针指向头结点
  61. {
  62. queue->rear = queue->front;
  63. }
  64. free(node);//释放旧的队头结点
  65. node = queue->front->next;
  66. }
  67. return OK;
  68. }
  69. /*
  70. 判断链队列是否为空队列
  71. */
  72. Status EmptyLinkQueue(LinkQueue* queue)
  73. {
  74. //空指针
  75. if (!queue)
  76. {
  77. return ERROR;
  78. }
  79. //空链队列
  80. if (queue->front == queue->rear)
  81. {
  82. return TRUE;
  83. }
  84. return FALSE;
  85. }
  86. /*
  87. 获取链队列长度
  88. */
  89. int LengthLinkQueue(LinkQueue* queue)
  90. {
  91. //空指针
  92. if (!queue)
  93. {
  94. return ERROR;
  95. }
  96. //空链队列
  97. if (queue->front == queue->rear)
  98. {
  99. return 0;
  100. }
  101. QueueNode* node = queue->front->next;
  102. int num = 0;
  103. while (node)
  104. {
  105. node = node->next;
  106. num++;
  107. }
  108. return num;
  109. }
  110. /*
  111. 在链队列队尾添加元素
  112. 先将新元素添加到链表尾部,然后将队列尾指针指向这个新元素
  113. */
  114. Status AddQueue(LinkQueue* queue,EleType e)
  115. {
  116. //空指针
  117. if (!queue)
  118. {
  119. return ERROR;
  120. }
  121. QueueNode* node = (QueueNode*)malloc(sizeof(QueueNode));
  122. if (!node)
  123. {
  124. return ERROR;
  125. }
  126. node->next = NULL;
  127. node->e = e;
  128. queue->rear->next = node;//将新结点添加到链表表中
  129. queue->rear = node;//队尾指针指向新的队尾结点
  130. return OK;
  131. }
  132. /*
  133. 从链队列中删除队头元素
  134. 先将头结结点指向新的队头结点,然后释放原来的队头结点
  135. */
  136. Status DelQueue(LinkQueue* queue, EleType *e)
  137. {
  138. //空指针
  139. if (!queue)
  140. {
  141. return ERROR;
  142. }
  143. //注意queue->front是头结点,头结点指向的结点才是队头结点
  144. QueueNode* node = queue->front->next;//旧队头结点
  145. *e = node->e;
  146. queue->front->next = node->next;//队头指针指向新的队头结点
  147. //当删除的是队尾元素时,将队尾指针指向头结点
  148. if (node = queue->rear)
  149. {
  150. queue->rear = queue->front;
  151. }
  152. return OK;
  153. }
  154. /*
  155. 打印链队列元素
  156. */
  157. void PrintfLinkQueue(LinkQueue* queue)
  158. {
  159. if (!queue)
  160. {
  161. return;
  162. }
  163. QueueNode* node = queue->front->next;
  164. while (node)
  165. {
  166. printf("%d,", node->e);
  167. node = node->next;
  168. }
  169. printf("\n");
  170. return;
  171. }
  172. int main(int argc, char *argv[])
  173. {
  174. LinkQueue queue;
  175. InitLinkQueue(&queue);
  176. AddQueue(&queue, 1);
  177. AddQueue(&queue, 2);
  178. AddQueue(&queue, 3);
  179. AddQueue(&queue, 4);
  180. AddQueue(&queue, 5);
  181. AddQueue(&queue, 6);
  182. AddQueue(&queue, 7);
  183. AddQueue(&queue, 8);
  184. AddQueue(&queue, 9);
  185. printf("链队列元素个数:%d\n",LengthLinkQueue(&queue));
  186. printf("展示元素:\n");
  187. PrintfLinkQueue(&queue);
  188. int e1, e2;
  189. DelQueue(&queue, &e1);
  190. DelQueue(&queue, &e2);
  191. printf("删除元素:%d,%d\n", e1, e2);
  192. printf("展示元素:\n");
  193. PrintfLinkQueue(&queue);
  194. printf("链队列元素个数:%d\n", LengthLinkQueue(&queue));
  195. CleaerLinkQueue(&queue);
  196. printf("清空元素后,长度为%d,rear = %p,front=%p",LengthLinkQueue(&queue), queue.rear,queue.front);
  197. printf("\n");
  198. return 0;
  199. }
验证结果截图:


对于循环队列与链队列的比较,可以从时间和空间2方面来考虑,从时间上,他们的基本操作都是常数时间,即都为O(1),不过循环队列是事先申请好空间,使用期间不释放,而对于链队列,每次申请和释放结点也会存在一些时间开销,如果入队出队频繁,则2者还是有些细微的差异。对于空间方面来说,循环队列必须有一个固定的长度,所以就有了存储元素个数和空间浪费的问题。而链队列就不存在这个问题,尽管它需要一些指针域,会产生一些空间上的开销,但也可以接受。所以在空间上,链队列更加灵活。





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

闽ICP备14008679号