当前位置:   article > 正文

数据结构——链式队列【c语言版】

链式队列

  队列(quque)简称队,只允许在表的一端输入,在表的另一端删除(操作受限制的线性表),

把进行插入的一段叫做队尾(表尾),把进入删除的一端叫做队首或队头(表头)。

队列最主要的特点:先进先出,FIFO(first in first out)

队列有其实有三种:顺序队列、 循环队列、链式队列

      采用链式存储结构实现的队列称为链队

        下面是采用单链表来实现链式队列的过程:

        在链队中只允许单链表的表头进行删除操作(出队),表尾进行插入操作(入队),因此需要使用两个指针(一个是对头指针front【指向队首结点】,另一个是队尾指针rear【指向队尾结点】)。 

链队数据结点类型DataNode如下:

  1. typedef int ElemType;
  2. //值节点--多个
  3. typedef struct Node
  4. {
  5. ElemType data;//存储队列的元素值
  6. struct Node *next;//存储下一个元素节点的地址
  7. }DataNode;

链队存储结构如图:

链队头结点类型LinkQueue如下:

  1. //头节点--1个
  2. typedef struct
  3. {
  4. DataNode *front;//存储队头元素节点的地址 (队首指针)
  5. DataNode *rear;//存储队尾元素节点的地址 (队尾指针)
  6. }LinkQueue;

链队的动态变化过程如图:

对于链式队列来说,有以下四个非常重要的要素:

        1.队空条件:q->front==NULL && q->rear==NULL 

        2.队满条件:与链栈一样,链队一般不会满,不存在队满上溢情况 

        3.进队操作:新建一个结点存放元素e,将结点t插入作为尾结点

        4.出队操作:构造一个结点t,让t指向队首元素节点,把队首元素存储到*e中,删除队头元                                   素节点

1)链队初始化

        构造一个空的队列,既创建一个链队结点,将front和rear域都设置为NULL,代码如下:

  1. LinkQueue *InitQueue()
  2. {
  3. LinkQueue *q;
  4. q=(LinkQueue *)malloc(sizeof(LinkQueue));
  5. q->front=NULL;
  6. q->rear=NULL;
  7. return q;
  8. }

2)销毁队列

        释放队列占用的全部存储空间,包括链队结点与所以数据结点的存储空间,代码如下:

  1. void DestroyQueue(LinkQueue *q)
  2. {
  3. int deQueue(LinkQueue *q,ElemType *e);
  4. ElemType m;
  5. while(q->front!=NULL||q->rear!=NULL)//非空
  6. {
  7. //出队
  8. deQueue(q,&m);
  9. }
  10. free(q);
  11. }

3)判断队列是否为空

        链式队列中,判断队列是否为空,只需要判断q->front==NULL && q->rear==NULL的条件成立即可,代码如下:

  1. //判断队列为空
  2. int QueueEmpty(LinkQueue *q)
  3. {
  4. if(q->front==NULL && q->rear==NULL)
  5. {
  6. return 1;
  7. }
  8. else
  9. {
  10. return 0;
  11. }
  12. }

4)入队

       构造一个节点t,data域存储e,next域存储NULL,若原链队为空,则将链队结点的两个域都指向结点t,否则将结点t链接到单链表末尾,并让链队结点的rear域指向它,代码如下:

  1. void enQueue(LinkQueue *q,ElemType e)
  2. {
  3. DataNode *t;
  4. //1.构造一个节点t,data域存储e,next域存储NULL
  5. t=(DataNode *)malloc(sizeof(DataNode));
  6. t->data=e;
  7. t->next=NULL;
  8. //2.添加
  9. if(q->front!=NULL||q->rear!=NULL)//非空
  10. {
  11. /*队非空*/
  12. q->rear->next=t;
  13. q->rear=t;
  14. }
  15. else
  16. {
  17. /*队空 */
  18. q->front=t;
  19. q->rear=t;
  20. }
  21. }

5)出队

         若原链队为空,则下溢,提示,返回0,否则将队首结点的data域赋值给*e,并删除队首结点,若原链队只有一个结点,则需要将链队结点的两个域都设置为NULL,表示此时链队已空,代码如下:

  1. /*
  2. 若队列非空,出队,返回1;
  3. 否则,提示,返回0
  4. */
  5. int deQueue(LinkQueue *q,ElemType *e)
  6. {
  7. DataNode *t;
  8. if(q->front!=NULL||q->rear!=NULL)//非空
  9. {
  10. //1.让t指向队头元素节点
  11. t=q->front;
  12. //2.把队头元素存储到*e中
  13. *e=t->data;
  14. //3.删除队头元素节点
  15. if(q->front->next==NULL)//只有1个元素
  16. {
  17. /*只有1个元素*/
  18. q->front=NULL;
  19. q->rear=NULL;
  20. }
  21. else
  22. {
  23. /*多于1个元素*/
  24. q->front=t->next;
  25. }
  26. //4.释放t所占的存储空间
  27. free(t);
  28. return 1;
  29. }
  30. else
  31. {
  32. printf("队空,不能出队!\n");
  33. return 0;
  34. }
  35. }

6)求队列长度

代码如下:

  1. /*
  2. 6.求链式队列的长度
  3. */
  4. int lenghtLinkQueue(LinkQueue *q)
  5. {
  6. int len;
  7. if (QueueEmpty(&q))
  8. {
  9. len = 0;
  10. return len;
  11. }
  12. DataNode *t;
  13. //1.构造一个节点t,让它指向队首元素front
  14. t=(DataNode *)malloc(sizeof(DataNode));
  15. t=q->front;
  16. len = 1;
  17. while(t->next != NULL)
  18. {
  19. len++;
  20. t = t->next;
  21. }
  22. printf("队列长度为%d\n",len);
  23. }

7)打印队列中的元素

        从队首到队尾,代码如下:

  1. //打印队列中的与元素
  2. void DispQueue(LinkQueue *q)
  3. {
  4. DataNode *p;
  5. p=q->front;
  6. printf("队列元素为:");
  7. while(p!=NULL)
  8. {
  9. printf("%d ",p->data);
  10. p=p->next;
  11. }
  12. printf("\n");
  13. }

下面是入队、出栈和打印出队列以及销毁队列元素的操作:

  1. int main()
  2. {
  3. LinkQueue lq;
  4. lq = *InitQueue();
  5. enQueue(&lq,1);
  6. enQueue(&lq,2);
  7. enQueue(&lq,3);
  8. enQueue(&lq,4);
  9. enQueue(&lq,5);
  10. enQueue(&lq,6);
  11. enQueue(&lq,7);
  12. enQueue(&lq,8);
  13. enQueue(&lq,9);
  14. DispQueue(&lq);
  15. lenghtLinkQueue(&lq);
  16. ElemType *e;
  17. e = (ElemType *)malloc(sizeof(ElemType));
  18. deQueue(&lq,e);
  19. printf("出队元素:%d\n",*e);
  20. deQueue(&lq,e);
  21. printf("出队元素:%d\n",*e);
  22. printf("队列为空返回1,否则返回0:%d\n",QueueEmpty(&lq));
  23. DispQueue(&lq);
  24. lenghtLinkQueue(&lq);
  25. DestroyQueue(&lq); //销毁队列
  26. return 1;
  27. }

测试结构如下

 

最后再附上完整代码:

  1. #include <stdio.h>
  2. typedef int ElemType;
  3. //值节点--多个
  4. typedef struct Node
  5. {
  6. ElemType data;//存储队列的元素值
  7. struct Node *next;//存储下一个元素节点的地址
  8. }DataNode;
  9. //头节点--1个
  10. typedef struct
  11. {
  12. DataNode *front;//存储队头元素节点的地址 (队首指针)
  13. DataNode *rear;//存储队尾元素节点的地址 (队尾指针)
  14. }LinkQueue;
  15. /*
  16. 空:q->front==NULL && q->rear==NULL
  17. 满:与链栈一样,链队一般不会满,不存在队满上溢情况
  18. */
  19. /*
  20. 1.初始化
  21. */
  22. LinkQueue *InitQueue()
  23. {
  24. LinkQueue *q;
  25. q=(LinkQueue *)malloc(sizeof(LinkQueue));
  26. q->front=NULL;
  27. q->rear=NULL;
  28. return q;
  29. }
  30. /*
  31. 2.销毁
  32. */
  33. void DestroyQueue(LinkQueue *q)
  34. {
  35. int deQueue(LinkQueue *q,ElemType *e);
  36. ElemType m;
  37. while(q->front!=NULL||q->rear!=NULL)//非空
  38. {
  39. //出队
  40. deQueue(q,&m);
  41. }
  42. free(q);
  43. }
  44. /*
  45. 3.判断是否为空
  46. 若为空,返回1;
  47. 否则,返回0
  48. */
  49. int QueueEmpty(LinkQueue *q)
  50. {
  51. if(q->front==NULL && q->rear==NULL)
  52. {
  53. return 1;
  54. }
  55. else
  56. {
  57. return 0;
  58. }
  59. }
  60. /*
  61. 4.进队
  62. */
  63. void enQueue(LinkQueue *q,ElemType e)
  64. {
  65. DataNode *t;
  66. //1.构造一个节点t,data域存储e,next域存储NULL
  67. t=(DataNode *)malloc(sizeof(DataNode));
  68. t->data=e;
  69. t->next=NULL;
  70. //2.添加
  71. if(q->front!=NULL||q->rear!=NULL)//非空
  72. {
  73. /*队非空*/
  74. q->rear->next=t;
  75. q->rear=t;
  76. }
  77. else
  78. {
  79. /*队空 */
  80. q->front=t;
  81. q->rear=t;
  82. }
  83. }
  84. /*
  85. 5.出队
  86. 若队列非空,出队,返回1;
  87. 否则,提示,返回0
  88. */
  89. int deQueue(LinkQueue *q,ElemType *e)
  90. {
  91. DataNode *t;
  92. if(q->front!=NULL||q->rear!=NULL)//非空
  93. {
  94. //1.让t指向队头元素节点
  95. t=q->front;
  96. //2.把队头元素存储到*e中
  97. *e=t->data; // 其实是q->front->data
  98. //3.删除队头元素节点
  99. if(q->front->next==NULL)//只有1个元素
  100. {
  101. /*只有1个元素*/
  102. q->front=NULL;
  103. q->rear=NULL;
  104. }
  105. else
  106. {
  107. /*多于1个元素*/
  108. q->front=t->next;
  109. }
  110. //4.释放t所占的存储空间
  111. free(t);
  112. return 1;
  113. }
  114. else
  115. {
  116. printf("队空,不能出队!\n");
  117. return 0;
  118. }
  119. }
  120. /*
  121. 6.求链式队列的长度
  122. */
  123. int lenghtLinkQueue(LinkQueue *q)
  124. {
  125. int len;
  126. if (QueueEmpty(&q))
  127. {
  128. len = 0;
  129. return len;
  130. }
  131. DataNode *t;
  132. //1.构造一个节点t,让它指向队首元素front
  133. t=(DataNode *)malloc(sizeof(DataNode));
  134. t=q->front;
  135. len = 1;
  136. while(t->next != NULL)
  137. {
  138. len++;
  139. t = t->next;
  140. }
  141. printf("队列长度为%d\n",len);
  142. }
  143. /*
  144. 7.输出
  145. */
  146. void DispQueue(LinkQueue *q)
  147. {
  148. DataNode *p;
  149. p=q->front;
  150. printf("队列元素为:");
  151. while(p!=NULL)
  152. {
  153. printf("%d ",p->data);
  154. p=p->next;
  155. }
  156. printf("\n");
  157. }
  158. int main()
  159. {
  160. LinkQueue lq;
  161. lq = *InitQueue();
  162. enQueue(&lq,1);
  163. enQueue(&lq,2);
  164. enQueue(&lq,3);
  165. enQueue(&lq,4);
  166. enQueue(&lq,5);
  167. enQueue(&lq,6);
  168. enQueue(&lq,7);
  169. enQueue(&lq,8);
  170. enQueue(&lq,9);
  171. DispQueue(&lq);
  172. lenghtLinkQueue(&lq);
  173. ElemType *e;
  174. e = (ElemType *)malloc(sizeof(ElemType));
  175. deQueue(&lq,e);
  176. printf("出队元素:%d\n",*e);
  177. deQueue(&lq,e);
  178. printf("出队元素:%d\n",*e);
  179. printf("队列为空返回1,否则返回0:%d\n",QueueEmpty(&lq));
  180. DispQueue(&lq);
  181. lenghtLinkQueue(&lq);
  182. DestroyQueue(&lq); //销毁队列
  183. return 1;
  184. }

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

闽ICP备14008679号