当前位置:   article > 正文

循环队列及链队列的基本操作_本关任务是实现循环队列的基本操作函数,以实现判断队列是否为满、是否为空、求队

本关任务是实现循环队列的基本操作函数,以实现判断队列是否为满、是否为空、求队

第1关:循环队列的基本操作

任务描述

本关任务是实现循环队列的基本操作函数,以实现判断队列是否为满、是否为空、求队列元素个数、进队和出队等功能。

相关知识

队列的基本概念

队列(简称队)也是一种运算受限的线性表,在这种线性表上,插入限定在表的某一端进行,删除限定在表的另一端进行。

队列的插入操作称为进队,删除操作称为出队

允许插入的一端称为队尾,允许删除的一端称为队头

新插入的元素只能添加到队尾,被删除的只能是排在队头的元素。

一个队列的示意图:

队列通常有两种存储结构,即顺序存储结构和链式存储结构。

队列的顺序存储结构简称为顺序队列,它由一个一维数组(用于存储队列中元素)及两个分别指示队头和队尾的变量组成,这两个变量分别称为“队头指针”和“队尾指针”。

通常约定队尾指针指示队尾元素的当前位置,队头指针指示队头元素的前一个位置

循环队列的类型定义

 
  1. #define MAX_QSIZE 5 // 最大队列长度+1
  2. struct SqQueue
  3. {
  4. QElemType *base; // 初始化的动态分配存储空间
  5. int front; // 头指针,若队列不空,指向队列头元素
  6. int rear; // 尾指针,若队列不空,指向队列尾元素的下一个位置
  7. };

使用顺序队列时会出现“假溢出现象”,为了能够充分地使用数组中的存储空间,可以把数组的前端和后端连接起来,形成一个环形的表,即把存储队列元素的表从逻辑上看成一个环。这个环形的表叫做循环队列

一个循环队列示意图:

队头队尾指针进1的操作为:

  • 队头指针进1:front=(front+1) MOD MaxSize
  • 队尾指针进1:rear=(rear+1) MOD MaxSize

为了在循环队列中区分队空和队满,规定:

  • 设置队空条件为front==rear。
  • 设置队满条件为(rear+1) MOD MaxSize==front。也就是说,当rear指到front的前一位置时就认为队列满了。

显然在这样设置的队满条件下,队满条件成立时队中还有一个空闲单元,也就是说这样的队中最多只能进队MaxSize-1个元素。

编程要求

根据提示,在右侧编辑器补充代码,编写循环队列的基本操作函数。

 
  1. void InitQueue(SqQueue &Q); // 构造一个空队列Q
  2. void DestroyQueue(SqQueue &Q); // 销毁队列Q,Q不再存在
  3. void ClearQueue(SqQueue &Q); // 将Q清为空队列
  4. int QueueEmpty(SqQueue Q); // 若队列Q为空队列,则返回TRUE;否则返回FALSE
  5. int QueueLength(SqQueue Q); // 返回Q的元素个数,即队列的长度
  6. int GetHead(SqQueue Q,QElemType &e); // 若队列不空,则用e返回Q的队头元素,并返回OK;否则返回ERROR
  7. int EnQueue(SqQueue &Q,QElemType e); // 插入元素e为Q的新的队尾元素
  8. int DeQueue(SqQueue &Q,QElemType &e); // 若队列不空,则删除Q的队头元素,用e返回其值,并返回OK;否则返回ERROR
  9. void QueueTraverse(SqQueue Q,void(*vi)(QElemType)); // 从队头到队尾依次对队列Q中每个元素调用函数vi()

测试说明

平台会对你编写的代码进行测试:

测试输入: 10 20 30 40 50 60

预期输出: 队列长度为: 4 现在队列中元素: 10 20 30 40 删除的元素是10 删除的元素是20 队列长度为: 3 现在队列中元素: 30 40 60 现在队头元素为:30

  1. #include <stdio.h>
  2. #include<stdlib.h>
  3. #include <iostream>
  4. using namespace std;
  5. // 函数结果状态代码
  6. #define TRUE 1
  7. #define FALSE 0
  8. #define OK 1
  9. #define ERROR 0
  10. #define OVERFLOW -1
  11. typedef int QElemType;
  12. #define MAX_QSIZE 5 // 最大队列长度+1
  13. struct SqQueue
  14. {
  15. QElemType *base; // 初始化的动态分配存储空间
  16. int front; // 头指针,若队列不空,指向队列头元素
  17. int rear; // 尾指针,若队列不空,指向队列尾元素的下一个位置
  18. };
  19. void print(QElemType i)
  20. {
  21. printf("%d ",i);
  22. }
  23. void InitQueue(SqQueue &Q); // 构造一个空队列Q
  24. void DestroyQueue(SqQueue &Q); // 销毁队列Q,Q不再存在
  25. void ClearQueue(SqQueue &Q); // 将Q清为空队列
  26. int QueueEmpty(SqQueue Q); // 若队列Q为空队列,则返回TRUE;否则返回FALSE
  27. int QueueLength(SqQueue Q); // 返回Q的元素个数,即队列的长度
  28. int GetHead(SqQueue Q,QElemType &e); // 若队列不空,则用e返回Q的队头元素,并返回OK;否则返回ERROR
  29. int EnQueue(SqQueue &Q,QElemType e); // 插入元素e为Q的新的队尾元素
  30. int DeQueue(SqQueue &Q,QElemType &e); // 若队列不空,则删除Q的队头元素,用e返回其值,并返回OK;否则返回ERROR
  31. void QueueTraverse(SqQueue Q,void(*vi)(QElemType)); // 从队头到队尾依次对队列Q中每个元素调用函数vi()
  32. int main()
  33. {
  34. int j;
  35. int i=0,l;
  36. QElemType d;
  37. SqQueue Q;
  38. InitQueue(Q);
  39. for(i=0;i<MAX_QSIZE;i++)
  40. {
  41. scanf("%d",&d);
  42. EnQueue(Q,d);
  43. };
  44. printf("队列长度为: %d\n",QueueLength(Q));
  45. printf("现在队列中元素:\n");
  46. QueueTraverse(Q,print);
  47. DeQueue(Q,d);
  48. printf("删除的元素是%d\n",d);
  49. DeQueue(Q,d);
  50. printf("删除的元素是%d\n",d);
  51. scanf("%d",&d);
  52. EnQueue(Q,d);
  53. printf("队列长度为: %d\n",QueueLength(Q));
  54. printf("现在队列中元素:\n");
  55. QueueTraverse(Q,print);
  56. j=GetHead(Q,d);
  57. if(j)
  58. printf("现在队头元素为:%d\n",d);
  59. ClearQueue(Q);
  60. DestroyQueue(Q);
  61. }
  62. // 循环队列的基本操作(9个)
  63. void InitQueue(SqQueue &Q)
  64. { // 构造一个空队列Q
  65. /********** Begin **********/
  66. Q.base=(QElemType*)malloc(MAX_QSIZE* sizeof(QElemType));
  67. Q.front=Q.rear=0;
  68. /********** End **********/
  69. }
  70. void DestroyQueue(SqQueue &Q)
  71. { // 销毁队列Q,Q不再存在
  72. /********** Begin **********/
  73. Q.front=Q.rear=0;
  74. /********** End **********/
  75. }
  76. void ClearQueue(SqQueue &Q)
  77. { // 将Q清为空队列
  78. /********** Begin **********/
  79. Q.front=Q.rear=0;
  80. /********** End **********/
  81. }
  82. int QueueEmpty(SqQueue Q)
  83. { // 若队列Q为空队列,则返回TRUE;否则返回FALSE
  84. /********** Begin **********/
  85. if(Q.front==Q.rear)
  86. return 1;
  87. else
  88. return 0;
  89. /********** End **********/
  90. }
  91. int QueueLength(SqQueue Q)
  92. { // 返回Q的元素个数,即队列的长度
  93. /********** Begin **********/
  94. return (Q.rear-Q.front+MAX_QSIZE)%MAX_QSIZE;
  95. /********** End **********/
  96. }
  97. int GetHead(SqQueue Q,QElemType &e)
  98. { // 若队列不空,则用e返回Q的队头元素,并返回OK;否则返回ERROR
  99. /********** Begin **********/
  100. if(Q.front==Q.rear) // 队列空
  101. return ERROR;
  102. e=Q.base[Q.front];
  103. return OK;
  104. /********** End **********/
  105. }
  106. int EnQueue(SqQueue &Q,QElemType e)
  107. { // 插入元素e为Q的新的队尾元素
  108. /********** Begin **********/
  109. if((Q.rear+1)%MAX_QSIZE==Q.front)
  110. return 0;
  111. Q.base[Q.rear]=e;
  112. Q.rear=(Q.rear+1)%MAX_QSIZE;
  113. return 1;
  114. /********** End **********/
  115. }
  116. int DeQueue(SqQueue &Q,QElemType &e)
  117. { // 若队列不空,则删除Q的队头元素,用e返回其值,并返回OK;否则返回ERROR
  118. /********** Begin **********/
  119. if(Q.rear==Q.front)
  120. return 0;
  121. e=Q.base[Q.front];
  122. Q.front=(Q.front+1)%MAX_QSIZE;
  123. return 1;
  124. /********** End **********/
  125. }
  126. void QueueTraverse(SqQueue Q,void(*vi)(QElemType))
  127. { // 从队头到队尾依次对队列Q中每个元素调用函数vi()
  128. /********** Begin **********/
  129. while(Q.rear!=Q.front)
  130. {
  131. vi(Q.base[Q.front]);
  132. Q.front=(Q.front+1)%MAX_QSIZE;
  133. }
  134. printf("\n");
  135. /********** End **********/
  136. }

 

第2关:链队列的基本操作

任务描述

本关任务是实现链队列的基本操作函数,以实现判断队列是否为满、是否为空、求队列元素个数、进队和出队等功能。

相关知识

链队列的基本概念

队列的链式存储结构简称为链队列

这里采用的链队是一个同时带有队头指针front队尾指针rear的单链表。

队头指针指向队头结点,队尾指针指向队尾结点即单链表的尾结点,并将队头和队尾指针结合起来构成链队结点,

链队列逻辑示意图:

下面给出一种链队列的实现方案。

链队列的类型定义

 
  1. typedef struct QNode
  2. {
  3. QElemType data;
  4. QNode *next;
  5. }*QueuePtr;
  6. struct LinkQueue
  7. {
  8. QueuePtr front,rear; // 队头、队尾指针
  9. };

编程要求

根据提示,在右侧编辑器补充代码,编写链队列的基本操作函数。

 
  1. void InitQueue(LinkQueue &Q); // 构造一个空队列Q
  2. void DestroyQueue(LinkQueue &Q); // 销毁队列Q,Q不再存在
  3. void ClearQueue(LinkQueue &Q); // 将Q清为空队列
  4. int QueueEmpty(LinkQueue Q); // 若队列Q为空队列,则返回TRUE;否则返回FALSE
  5. int QueueLength(LinkQueue Q); // 返回Q的元素个数,即队列的长度
  6. int GetHead(LinkQueue Q,QElemType &e); // 若队列不空,则用e返回Q的队头元素,并返回OK;否则返回ERROR
  7. int EnQueue(LinkQueue &Q,QElemType e); // 插入元素e为Q的新的队尾元素
  8. int DeQueue(LinkQueue &Q,QElemType &e); // 若队列不空,则删除Q的队头元素,用e返回其值,并返回OK;否则返回ERROR
  9. void QueueTraverse(LinkQueue Q,void(*vi)(QElemType)); // 从队头到队尾依次对队列Q中每个元素调用函数vi()

测试说明

平台会对你编写的代码进行测试:

测试输入: 10 20 30 40 50 60

预期输出: 队列长度为: 5 现在队列中元素: 10 20 30 40 50 删除的元素是10 删除的元素是20 队列长度为: 4 现在队列中元素: 30 40 50 60 现在队头元素为:30

  1. #include <stdio.h>
  2. #include<stdlib.h>
  3. #include <iostream>
  4. using namespace std;
  5. // 函数结果状态代码
  6. #define TRUE 1
  7. #define FALSE 0
  8. #define OK 1
  9. #define ERROR 0
  10. #define OVERFLOW -1
  11. typedef int QElemType;
  12. typedef struct QNode
  13. {
  14. QElemType data;
  15. QNode *next;
  16. }*QueuePtr;
  17. struct LinkQueue
  18. {
  19. QueuePtr front,rear; // 队头、队尾指针
  20. };
  21. void print(QElemType i)
  22. {
  23. printf("%d ",i);
  24. }
  25. void InitQueue(LinkQueue &Q); // 构造一个空队列Q
  26. void DestroyQueue(LinkQueue &Q); // 销毁队列Q,Q不再存在
  27. void ClearQueue(LinkQueue &Q); // 将Q清为空队列
  28. int QueueEmpty(LinkQueue Q); // 若队列Q为空队列,则返回TRUE;否则返回FALSE
  29. int QueueLength(LinkQueue Q); // 返回Q的元素个数,即队列的长度
  30. int GetHead(LinkQueue Q,QElemType &e); // 若队列不空,则用e返回Q的队头元素,并返回OK;否则返回ERROR
  31. int EnQueue(LinkQueue &Q,QElemType e); // 插入元素e为Q的新的队尾元素
  32. int DeQueue(LinkQueue &Q,QElemType &e); // 若队列不空,则删除Q的队头元素,用e返回其值,并返回OK;否则返回ERROR
  33. void QueueTraverse(LinkQueue Q,void(*vi)(QElemType)); // 从队头到队尾依次对队列Q中每个元素调用函数vi()
  34. int main()
  35. {
  36. int j;
  37. int i=0,l;
  38. QElemType d;
  39. LinkQueue Q;
  40. InitQueue(Q);
  41. for(i=0;i<5;i++)
  42. {
  43. scanf("%d",&d);
  44. EnQueue(Q,d);
  45. };
  46. printf("队列长度为: %d\n",QueueLength(Q));
  47. printf("现在队列中元素:\n");
  48. QueueTraverse(Q,print);
  49. DeQueue(Q,d);
  50. printf("删除的元素是%d\n",d);
  51. DeQueue(Q,d);
  52. printf("删除的元素是%d\n",d);
  53. scanf("%d",&d);
  54. EnQueue(Q,d);
  55. printf("队列长度为: %d\n",QueueLength(Q));
  56. printf("现在队列中元素:\n");
  57. QueueTraverse(Q,print);
  58. j=GetHead(Q,d);
  59. if(j)
  60. printf("现在队头元素为:%d\n",d);
  61. ClearQueue(Q);
  62. DestroyQueue(Q);
  63. }
  64. // 链队列的基本操作(9个)
  65. void InitQueue(LinkQueue &Q)
  66. { // 构造一个空队列Q
  67. /********** Begin **********/
  68. Q.rear=Q.front=(QueuePtr)malloc(sizeof(QNode));
  69. /********** End **********/
  70. }
  71. void DestroyQueue(LinkQueue &Q)
  72. { // 销毁队列Q(无论空否均可)
  73. /********** Begin **********/
  74. while(Q.front)
  75. {
  76. Q.rear=Q.front->next;
  77. free(Q.front);
  78. Q.front=Q.rear;
  79. }
  80. /********** End **********/
  81. }
  82. void ClearQueue(LinkQueue &Q)
  83. { // 将Q清为空队列
  84. /********** Begin **********/
  85. QueuePtr q=Q.front,s;
  86. Q.front=Q.rear;
  87. while(q->next)
  88. {
  89. s=q;
  90. q=q->next;
  91. }
  92. /********** End **********/
  93. }
  94. int QueueEmpty(LinkQueue Q)
  95. { // 若Q为空队列,则返回TRUE,否则返回FALSE
  96. /********** Begin **********/
  97. if(Q.front->next==NULL)
  98. {
  99. return 1;
  100. }
  101. else
  102. return 0;
  103. /********** End **********/
  104. }
  105. int QueueLength(LinkQueue Q)
  106. { // 求队列的长度
  107. /********** Begin **********/
  108. QueuePtr q=Q.front;
  109. int count=0;
  110. while(q!=Q.rear)
  111. {
  112. count++;
  113. q=q->next;
  114. }
  115. return count;
  116. /********** End **********/
  117. }
  118. int GetHead(LinkQueue Q,QElemType &e)
  119. { // 若队列不空,则用e返回Q的队头元素,并返回OK,否则返回ERROR
  120. /********** Begin **********/
  121. QueuePtr q;
  122. if(Q.rear==Q.front)
  123. {
  124. return 0;
  125. }
  126. q=Q.front->next;
  127. e=q->data;
  128. return 1;
  129. /********** End **********/
  130. }
  131. int EnQueue(LinkQueue &Q,QElemType e)
  132. { // 插入元素e为Q的新的队尾元素
  133. /********** Begin **********/
  134. QueuePtr q=(QueuePtr)malloc(sizeof(QNode));
  135. q->data=e;
  136. q->next=NULL;
  137. Q.rear->next=q;
  138. Q.rear=q;
  139. /********** End **********/
  140. }
  141. int DeQueue(LinkQueue &Q,QElemType &e)
  142. { // 若队列不空,删除Q的队头元素,用e返回其值,并返回OK,否则返回ERROR
  143. /********** Begin **********/
  144. QueuePtr p;
  145. if(Q.front==Q.rear)
  146. return 0;
  147. p=Q.front->next;
  148. e=p->data;
  149. Q.front->next=p->next;
  150. if(Q.rear==p)
  151. Q.rear=Q.front;
  152. return 1;
  153. /********** End **********/
  154. }
  155. void QueueTraverse(LinkQueue Q,void(*vi)(QElemType))
  156. { // 从队头到队尾依次对队列Q中每个元素调用函数vi()
  157. /********** Begin **********/
  158. QueuePtr q=Q.front->next;
  159. while(q!=NULL)
  160. {
  161. vi(q->data);
  162. q=q->next;
  163. }
  164. printf("\n");
  165. /********** End **********/
  166. }

 

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

闽ICP备14008679号