当前位置:   article > 正文

【数据结构】 链队列的基本操作 (C语言版)

【数据结构】 链队列的基本操作 (C语言版)

目录

一、链队列

1、链栈的定义:

2、链栈的优缺点:

二、链队列的基本操作算法(C语言)    

1、宏定义

  2、创建结构体

3、链栈的初始化 

4、链队列的入队 

5、链队列的出队

6、取链队列的对头元素

7、链队列的销毁

8、链队列的清空

9、判断链队列是否为空

10、求队列长度

 11、遍历队列元素

三、链队列的基本操作完整代码(C语言)

  四、运行结果


一、链队列

1、链栈的定义:

链队列是一种线性数据结构,采用链表来实现队列的操作。链队列具有队头指针和队尾指针,用于指示队列元素所在的位置。链队列只允许在队尾插入元素,在队头删除元素,符合先进先出(First In First Out,FIFO)的原则。

2、链栈的优缺点:

链队列的优点:

  1. 动态分配空间:链队列使用链表实现,可动态分配和释放空间。因此,不需要预先分配大量存储空间,可以根据实际需求进行空间分配。
  2. 无需移动元素:相比普通队列,链队列在删除元素时无需移动大量元素,只需修改指针即可。这使得链队列在处理大规模数据时具有更高的效率。
  3. 适合处理用户排队等待的情况:链队列适用于处理用户排队等待的情况,例如银行排队、网络请求等。通过链队列,可以快速地插入新用户和删除已处理的用户。

链队列的缺点:

  1. 需要额外的存储空间:为了实现链表结构,链队列需要额外的存储空间来维护指针和节点。这会增加存储空间的消耗。
  2. 插入和删除操作可能引起内存分配和释放:在链队列中插入和删除元素时,可能需要动态分配和释放内存。这会增加操作的时间复杂度,并可能引起内存碎片化问题。
  3. 无法充分利用连续空间的优势:链表结构使得链队列无法像数组一样充分利用连续空间的优势,这会影响空间利用率和访问速度。

二、链队列的基本操作算法(C语言)    

1、宏定义
  1. #define OK 1
  2. #define ERROR 0
  3. #define OVERFLOW -1
  4. #define MAXSIZE 100
  5. typedef int QElemtype;
  6. typedef int Status;
  2、创建结构体
  1. //创建结构体
  2. typedef struct QNode {
  3. QElemtype data;
  4. struct QNode *next;
  5. } QNode, *QueuePtr;
  6. typedef struct {
  7. QueuePtr front;
  8. QueuePtr rear;
  9. } LinkQueue;
3、链栈的初始化 
  1. //链队列的初始化
  2. Status InitQueue(LinkQueue &Q) {
  3. Q.front = Q.rear = (QueuePtr) malloc(sizeof(QNode));
  4. if (!Q.front) {
  5. exit(OVERFLOW);
  6. }
  7. Q.front->next = NULL;
  8. return OK;
  9. }
4、链队列的入队 
  1. //链队列的入队
  2. Status EnQueue(LinkQueue &Q, QElemtype e) {
  3. QueuePtr p = (QueuePtr) malloc(sizeof(QNode));
  4. if (!p) {
  5. exit(OVERFLOW);
  6. }
  7. p->data = e;
  8. p->next = NULL;
  9. Q.rear->next = p;
  10. Q.rear = p;
  11. return OK;
  12. }
5、链队列的出队
  1. //链队列的出队
  2. Status DeQueue(LinkQueue &Q, QElemtype &e) {
  3. if (Q.front == Q.rear) {
  4. return ERROR;
  5. }
  6. QueuePtr p = Q.front->next;
  7. e = p->data;
  8. Q.front->next = p->next;
  9. if (Q.rear == p) {
  10. Q.rear = Q.front;
  11. }
  12. delete p;
  13. return OK;
  14. }
6、取链队列的对头元素
  1. //取链列的对头元素
  2. Status GetQueueHead(LinkQueue &Q, QElemtype &e) {
  3. if (Q.front == Q.rear) {
  4. return ERROR;
  5. }
  6. e = Q.front->next->data;
  7. return OK;
  8. }
7、链队列的销毁
  1. //队列的销毁
  2. Status DestoryQueue(LinkQueue &Q) {
  3. while (Q.front) {
  4. Q.rear = Q.front->next;
  5. delete (Q.front);
  6. Q.front = Q.rear;
  7. }
  8. // printf("销毁成功!");
  9. return OK;
  10. }
8、链队列的清空
  1. //清空
  2. Status ClearQueue(LinkQueue &Q) {
  3. Q.rear = Q.front->next;
  4. while (Q.front->next) {
  5. Q.rear = Q.rear->next;
  6. delete (Q.front->next);
  7. Q.front->next = Q.rear;
  8. }
  9. Q.rear = Q.front;
  10. // printf("清空成功!");
  11. return OK;
  12. }
9、判断链队列是否为空
  1. //判断是否为空
  2. Status QueueEmpty(LinkQueue &Q) {
  3. if (Q.front == Q.rear) {
  4. // printf("队列为空!\n");
  5. return true;
  6. } else {
  7. return false;
  8. }
  9. // printf("该队列不为空!");
  10. }
10、求队列长度
  1. //求队列长度
  2. Status QueueLength(LinkQueue Q) {
  3. int i = 0;
  4. while (Q.front != Q.rear) {
  5. i++;
  6. Q.front = Q.front->next;
  7. }
  8. // printf("该队列长度为:%d", i);
  9. return i;
  10. }
 11、遍历队列元素
  1. //遍历队列
  2. Status QueueTraverse(LinkQueue Q) {
  3. QNode *p;
  4. if (Q.front == Q.rear) {
  5. return ERROR;
  6. }
  7. p = Q.front->next;//存储头元素
  8. printf("从队头依次读出该队列中的元素值为: ");
  9. while (p != NULL) {
  10. printf("%d ", p->data);
  11. p = p->next;
  12. }
  13. printf("\n");
  14. return OK;
  15. }

三、链队列的基本操作完整代码(C语言)

  1. #include<stdio.h>
  2. #include<stdlib.h>
  3. #define OK 1
  4. #define ERROR 0
  5. #define OVERFLOW -1
  6. #define MAXSIZE 100
  7. typedef int QElemtype;
  8. typedef int Status;
  9. //创建结构体
  10. typedef struct QNode {
  11. QElemtype data;
  12. struct QNode *next;
  13. } QNode, *QueuePtr;
  14. typedef struct {
  15. QueuePtr front;
  16. QueuePtr rear;
  17. } LinkQueue;
  18. //链队列的初始化
  19. Status InitQueue(LinkQueue &Q) {
  20. Q.front = Q.rear = (QueuePtr) malloc(sizeof(QNode));
  21. if (!Q.front) {
  22. exit(OVERFLOW);
  23. }
  24. Q.front->next = NULL;
  25. return OK;
  26. }
  27. //链队列的入队
  28. Status EnQueue(LinkQueue &Q, QElemtype e) {
  29. QueuePtr p = (QueuePtr) malloc(sizeof(QNode));
  30. if (!p) {
  31. exit(OVERFLOW);
  32. }
  33. p->data = e;
  34. p->next = NULL;
  35. Q.rear->next = p;
  36. Q.rear = p;
  37. return OK;
  38. }
  39. //链队列的出队
  40. Status DeQueue(LinkQueue &Q, QElemtype &e) {
  41. if (Q.front == Q.rear) {
  42. return ERROR;
  43. }
  44. QueuePtr p = Q.front->next;
  45. e = p->data;
  46. Q.front->next = p->next;
  47. if (Q.rear == p) {
  48. Q.rear = Q.front;
  49. }
  50. delete p;
  51. return OK;
  52. }
  53. //取链列的对头元素
  54. Status GetQueueHead(LinkQueue &Q, QElemtype &e) {
  55. if (Q.front == Q.rear) {
  56. return ERROR;
  57. }
  58. e = Q.front->next->data;
  59. return OK;
  60. }
  61. //队列的销毁
  62. Status DestoryQueue(LinkQueue &Q) {
  63. while (Q.front) {
  64. Q.rear = Q.front->next;
  65. delete (Q.front);
  66. Q.front = Q.rear;
  67. }
  68. // printf("销毁成功!");
  69. return OK;
  70. }
  71. //清空
  72. Status ClearQueue(LinkQueue &Q) {
  73. Q.rear = Q.front->next;
  74. while (Q.front->next) {
  75. Q.rear = Q.rear->next;
  76. delete (Q.front->next);
  77. Q.front->next = Q.rear;
  78. }
  79. Q.rear = Q.front;
  80. // printf("清空成功!");
  81. return OK;
  82. }
  83. //判断是否为空
  84. Status QueueEmpty(LinkQueue &Q) {
  85. if (Q.front == Q.rear) {
  86. // printf("队列为空!\n");
  87. return true;
  88. } else {
  89. return false;
  90. }
  91. // printf("该队列不为空!");
  92. }
  93. //求队列长度
  94. Status QueueLength(LinkQueue Q) {
  95. int i = 0;
  96. while (Q.front != Q.rear) {
  97. i++;
  98. Q.front = Q.front->next;
  99. }
  100. // printf("该队列长度为:%d", i);
  101. return i;
  102. }
  103. //遍历队列
  104. Status QueueTraverse(LinkQueue Q) {
  105. QNode *p;
  106. if (Q.front == Q.rear) {
  107. return ERROR;
  108. }
  109. p = Q.front->next;//存储头元素
  110. printf("从队头依次读出该队列中的元素值为: ");
  111. while (p != NULL) {
  112. printf("%d ", p->data);
  113. p = p->next;
  114. }
  115. printf("\n");
  116. return OK;
  117. }
  118. //功能菜单列表
  119. void show_help() {
  120. printf("******* 功能菜单列表 *******\n");
  121. printf("1----入队------------------\n");
  122. printf("2----求链队列长度----------\n");
  123. printf("3----出队------------------\n");
  124. printf("4----取队头元素-------------\n");
  125. printf("5----清空循环队列-----------\n");
  126. printf("6----销毁循环队列-----------\n");
  127. printf("7----判断循环队列是否为空-----\n");
  128. printf("8----批量插入元素------------\n");
  129. printf("9----显示队列元素------------\n");
  130. printf("10----退出------------------\n\n");
  131. }
  132. //主函数
  133. int main() {
  134. LinkQueue LQ;
  135. Status reIn = InitQueue(LQ);
  136. if (reIn == OK) {
  137. printf("链队列初始时成功 \n");
  138. } else {
  139. printf("链队列初始时失败 \n");
  140. }
  141. while (1) {
  142. //功能菜单列表
  143. show_help();
  144. int flag;
  145. printf("请输入所需的功能编号:\n");
  146. scanf("%d", &flag);
  147. switch (flag) {
  148. case 1: {//入队
  149. Status EnQueueindex;
  150. printf("请输入插入元素(请在英文状态下输入例如:1): \n");
  151. scanf("%d", &EnQueueindex);
  152. Status rEnQueue = EnQueue(LQ, EnQueueindex);
  153. if (rEnQueue == OK) {
  154. printf("向链队列入队%d成功!\n", EnQueueindex);
  155. } else {
  156. printf("向链队列入队失败!\n");
  157. }
  158. }
  159. break;
  160. case 2: {//求链队列的长度
  161. int length = QueueLength(LQ);
  162. printf("链队列的长度为:%d。 \n\n", length);
  163. }
  164. break;
  165. case 3: {//出队
  166. QElemtype DeElem;
  167. Status DeEn = DeQueue(LQ, DeElem);
  168. if (DeEn == OK) {
  169. printf("从链队列中出队成功,出队的元素为 %d! \n", DeElem);
  170. } else {
  171. printf("从链队列中出队失败!\n");
  172. }
  173. }
  174. break;
  175. case 4: {//求队头元素
  176. QElemtype getEl;
  177. Status reGet = GetQueueHead(LQ, getEl);
  178. if (reGet == OK) {
  179. printf("从链队列中取对头元素成功,队头元素为:%d! \n", getEl);
  180. } else {
  181. printf("从链队列中取对头元素成功 \n");
  182. }
  183. }
  184. break;
  185. case 5: { //清空
  186. Status rClearStack = ClearQueue(LQ);
  187. if (rClearStack == OK) {
  188. printf("链队列清空成功!\n");
  189. } else {
  190. printf("链队列清空失败!\n");
  191. }
  192. }
  193. break;
  194. case 6: {//销毁
  195. Status rDestroyStack = DestoryQueue(LQ);
  196. if (rDestroyStack == OK) {
  197. printf("链队列销毁成功!\n");
  198. } else {
  199. printf("链队列销毁失败!\n");
  200. }
  201. }
  202. break;
  203. case 7: {///判空
  204. Status ClearStatus = QueueEmpty(LQ);
  205. if (ClearStatus == true) {
  206. printf("链队列为空!\n\n");
  207. } else {
  208. printf("链队列不为空!\n\n");
  209. }
  210. }
  211. break;
  212. case 8: {//批量插入
  213. int on;
  214. printf("请输入想要插入的元素个数:\n");
  215. scanf("%d", &on);
  216. QElemtype array[on];
  217. for (int i = 1; i <= on; i++) {
  218. printf("向链队列第%d个位置插入元素为:", i);
  219. scanf("%d", &array[i]);
  220. }
  221. for (int i = 1; i <= on; i++) {
  222. Status InsertStatus = EnQueue(LQ, array[i]);
  223. if (InsertStatus == OK) {
  224. printf("向链队列第%d个位置插入元素%d成功!\n", i, array[i]);
  225. } else {
  226. printf("向链队列第%d个位置插入元素%d失败!\n", i, array[i]);
  227. }
  228. }
  229. }
  230. break;
  231. case 9: {//输出链表元素
  232. QueueTraverse(LQ);
  233. // printf("\n");
  234. }
  235. break;
  236. case 10: {//退出程序
  237. return 0;
  238. }
  239. break;
  240. default: {
  241. printf("输入错误,无此功能,请检查输入:\n\n");
  242. }
  243. }
  244. }
  245. return 1;
  246. }

  四、运行结果

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

闽ICP备14008679号