当前位置:   article > 正文

队列---链队列:队列的链式存储结构

为节点s插入指针域赋值
一、链队列的基本结构

队列的链式存储结构,其实就是线性表的单链表,只不过它只能尾进头出而已,我们把它简称为链队列。

为了操作上的方便,我们将队头指针指向链队列的头结点,而队尾指针指向终端结点。链队列示意图:

20151021172624515

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

20151021172713989

二、链队列结构体定义

链队列结构体的定义,需要两个步骤:
(1)链队列节点的定义

  1. /* QElemType类型根据实际情况而定,这里假设为int */
  2. typedef int QElemType;
  3. typedef struct QNode /* 结点结构 */
  4. {
  5. QElemType data;
  6. struct QNode *next;
  7. } QNode;

(2) LinkQueue的结构体定义。只要定义队头和队尾指针即可。

  1. typedef struct /* 队列的链表结构 */
  2. {
  3. QNode *front; /* 队头、队尾指针 */
  4. QNode *rear;
  5. } LinkQueue;

三、实现要点

1、初始化。

链队列的初始化可以依据单链表的初始化,单链表的初始化是这样的:

(1)首先产生头结点(分配内存空间),并使L指向此头结点:

L=(LinkList*)malloc(sizeof(Node));

(2)再将指针域置空:L->next=NULL;

因此,链队列的初始化如下:

(1)产生头结点 (LinkQueue)malloc(sizeof(LinkQueue)),然后让队头指针(头指
针)与队尾指针都指向头结点。
(2)置空头结点 Q->front 的指针域 Q->front->next=NULL;

代码如下:

  1. /* 构造一个空队列q */
  2. LinkQueue *InitQueue(LinkQueue *q)
  3. {
  4. q->front = q->next =(QNode*)malloc(sizeof(QNode));
  5. q->front->next = NULL;
  6. return q;
  7. }

2、入队。入队操作就是在链队列的尾部插入结点。

20151021205517313

如上图,入队操作步骤大致如(1)(2)所示。实现算法为:

(1)创建结点s,QNode p=(QNode)malloc(sizeof(QNode));
(2)给s的data域赋值e,指针域next赋值null。p->data=e;p->next=NULL; 目的
是让它成为新的队尾元素。
(3)前任队尾元素呢?直接让它的指针域指向p。Q->rear->next=p;
(4)把队尾指针重新指向新任队尾s。Q->rear=p;

3、出队。出队操作时,就是头结点的后继结点(队头)出队,将头结点的后继改为它后面的结点,若链表除头结点外只剩一个元素时,则需将rear指向头结点。

一般情况下,链队列的出队图示:
20151021214927383

如果链队列只剩下一个元素的时候,出队则如下图:

20151021215110801

具体步骤:
(1)如图中,要删除掉a1结点,思路很简单,就是让头结点Q->front的后继next直接指向a2。但是a2如何标识呢?
(2)假设a1结点为p结点,那么a2就是p->next了。如何让a1结点存到p呢?
(3)直接让头结点的后继指向p就行,p=Q->front->next;
(4)假如队尾已经是p结点的话(Q->rear==p),队尾指针需要指向头结点Q->rear=Q->front;
(5)最后把p free掉。

四、链队列代码实现
  1. #include <iostream>
  2. #include<stdlib.h>
  3. using namespace std;
  4. typedef int QElemType;
  5. typedef struct QNode
  6. {
  7. QElemType data;
  8. struct QNode *next;
  9. }QNode;
  10. typedef struct
  11. {
  12. QNode *front;
  13. QNode *rear;
  14. }LinkQueue;
  15. // 构造一个空队列q
  16. LinkQueue *InitQueue(LinkQueue *q)
  17. {
  18. q->front = q->rear =(QNode*)malloc(sizeof(QNode));
  19. q->front->next = NULL;
  20. return q;
  21. }
  22. // 元素入队
  23. LinkQueue *EnQueue(LinkQueue *q, QElemType e)
  24. {
  25. QNode *p = (QNode*)malloc(sizeof(QNode));//为插入节点分配空间
  26. if(!p)
  27. {//分配空间失败
  28. cout<<"插入节点内存分配失败!"<<endl;
  29. }
  30. else
  31. { //建节点
  32. p->data = e; //为插入节点数据域赋值
  33. p->next = NULL;//为插入节点指针域赋值
  34. //实现插入
  35. q->rear->next = p;//插入到队尾
  36. q->rear = p;//队尾指针重新指向新任队尾
  37. }
  38. return q;
  39. }
  40. //元素出队
  41. LinkQueue *DeQueue(LinkQueue *q)
  42. {
  43. QNode *p;
  44. if(q->front == q->rear)
  45. {
  46. cout<<"链队列已空,不可再执行删除操作!"<<endl;
  47. }
  48. else
  49. {
  50. p = q->front->next;//将欲删除的队头结点暂存给p
  51. QElemType e = p->data;//把队头数据赋给e
  52. cout<<"delete: "<<e<<endl;
  53. q->front->next = p->next;//删除,将原队头结点的后继p->next赋值给头结点后继
  54. if(q->rear == p)
  55. {//若队头就是队尾,则删除后将rear指向头结点
  56. cout<<"链队列数据全部删除完毕!"<<endl;
  57. q->rear = q->front;
  58. }
  59. free(p);
  60. }
  61. return q;
  62. }
  63. //返回队头元素
  64. void GetQHead(LinkQueue *q)
  65. {
  66. QNode *p;
  67. if(q->front == q->rear)
  68. {
  69. cout<<"链队列为空,无法返回队头数据"<<endl;
  70. }
  71. else
  72. {
  73. p = q->front->next;//队头
  74. cout<<"队头元素:"<<p->data<<endl;
  75. }
  76. }
  77. //求队列长度
  78. void QueueLength(LinkQueue *q)
  79. {
  80. int length = 0;
  81. QNode *p;
  82. p = q->front->next;//队头
  83. while(p)
  84. {
  85. length++;
  86. p = p->next;
  87. }
  88. cout<<"队列长度:"<<length<<endl;
  89. }
  90. //打印。带头结点,真正存储元素的位置从头结点下一位置(队头)开始!!!
  91. void PrintQueue(LinkQueue *q)
  92. {
  93. QNode *p;//队头
  94. p = q->front->next;//头结点的下一节点,即为队头!!!
  95. while(p)
  96. {//从队头开始,依次往后遍历
  97. cout<<p->data<<" ";
  98. p = p->next;
  99. }
  100. cout<<endl;
  101. }
  102. int main()
  103. {
  104. LinkQueue *q = InitQueue(q);
  105. EnQueue(q, 1);
  106. PrintQueue(q);
  107. EnQueue(q, 2);
  108. PrintQueue(q);
  109. EnQueue(q, 3);
  110. PrintQueue(q);
  111. EnQueue(q, 4);
  112. PrintQueue(q);
  113. GetQHead(q);
  114. QueueLength(q);
  115. cout<<"***************"<<endl;
  116. DeQueue(q);
  117. PrintQueue(q);
  118. GetQHead(q);
  119. DeQueue(q);
  120. PrintQueue(q);
  121. GetQHead(q);
  122. DeQueue(q);
  123. PrintQueue(q);
  124. DeQueue(q);
  125. PrintQueue(q);
  126. QueueLength(q);
  127. cout<<"***************"<<endl;
  128. DeQueue(q);
  129. cout<<"***************"<<endl;
  130. return 0;
  131. }

输出结果:

  1. 1
  2. 1 2
  3. 1 2 3
  4. 1 2 3 4
  5. 队头元素:1
  6. 队列长度:4
  7. ***************
  8. delete: 1
  9. 2 3 4
  10. 队头元素:2
  11. delete: 2
  12. 3 4
  13. 队头元素:3
  14. delete: 3
  15. 4
  16. delete: 4
  17. 链队列数据全部删除完毕!
  18. 队列长度:0
  19. ***************
  20. 链队列已空,不可再执行删除操作!
  21. ***************
  22. Process returned 0 (0x0) execution time : 0.053 s
  23. Press any key to continue.

更多参考

转载于:https://www.cnblogs.com/ZY-Dream/p/10082621.html

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

闽ICP备14008679号