当前位置:   article > 正文

【数据结构】实验六:队列_队列实验

队列实验

实验六  队列

一、实验目的与要求

1)熟悉C/C++语言(或其他编程语言)的集成开发环境;

2)通过本实验加深对队列的理解,熟悉基本操作;

3  结合具体的问题分析算法时间复杂度。

二、实验内容

  设计你的循环队列实现。 循环队列是一种线性数据结构,其操作表现基于 FIFO(先进先出)原则并且队尾被连接在队首之后以形成一个循环。它也被称为“环形缓冲器”。

  循环队列的一个好处是我们可以利用这个队列之前用过的空间。在一个普通队列里,一旦一个队列满了,我们就不能插入下一个元素,即使在队列前面仍有空间。但是使用循环队列,我们能使用这些空间去存储新的值。

你的实现应该支持如下操作:

MyCircularQueue(k): 构造器,设置队列长度为 k 。

Front: 从队首获取元素。如果队列为空,返回 -1 。

Rear: 获取队尾元素。如果队列为空,返回 -1 。

enQueue(value): 向循环队列插入一个元素。如果成功插入则返回真。

deQueue(): 从循环队列中删除一个元素。如果成功删除则返回真。

isEmpty(): 检查循环队列是否为空。

isFull(): 检查循环队列是否已满。

三、实验结果

1)请将调试通过的源代码粘贴在下面。(代码注意书写规范、主要模块要有功能注释)

源代码:

  1. #include <iostream>
  2. using namespace std;
  3. template <typename T>
  4. class MyCircularQueue{
  5. T * data;//当前位置的数据
  6. int front,rear,size;//头指针、尾指针、队列长度
  7. public:
  8. //MyCircularQueue(k): 构造器,设置队列长度为 k 。
  9. MyCircularQueue(int k=0){
  10. data=new T[k+1];//k+1 -> 区分isEmpty和isFull的判断条件
  11. front=rear=0;
  12. size=k+1;
  13. }
  14. //Front: 从队首获取元素。如果队列为空,返回 -1 。
  15. T Front(){
  16. if(isEmpty()){
  17. return -1;
  18. }
  19. else{
  20. return data[front];
  21. }
  22. }
  23. //Rear: 获取队尾元素。如果队列为空,返回 -1 。
  24. T Rear(){
  25. if(isEmpty()){
  26. return -1;
  27. }
  28. else{
  29. return data[rear-1];
  30. }
  31. }
  32. //enQueue(value): 向循环队列插入一个元素。如果成功插入则返回真。
  33. bool enQueue(T value){
  34. if(isFull()){
  35. return 0;
  36. }
  37. else{
  38. data[rear]=value;
  39. rear=(rear+1)%size;
  40. return 1;
  41. }
  42. }
  43. //deQueue(): 从循环队列中删除一个元素。如果成功删除则返回真。
  44. bool deQueue(){
  45. if(isEmpty()){
  46. return 0;
  47. }
  48. else{
  49. front=(front+1)%size;
  50. return 1;
  51. }
  52. }
  53. //isEmpty(): 检查循环队列是否为空。
  54. bool isEmpty(){
  55. if(rear==front){
  56. return 1;
  57. }
  58. else{
  59. return 0;
  60. }
  61. }
  62. //isFull(): 检查循环队列是否已满。
  63. bool isFull(){
  64. if((rear+1)%size==front){
  65. return 1;
  66. }
  67. else{
  68. return 0;
  69. }
  70. }
  71. };
  72. int main(){
  73. //初始化循环链表
  74. int len;
  75. cout<<"Please input the length of your queue"<<endl;
  76. cin>>len;
  77. MyCircularQueue <int> queue(len);
  78. //查看空表
  79. if(queue.isEmpty() ==1){
  80. cout<<"The current queue is empty"<<endl;
  81. }
  82. else{
  83. cout<<"The current queue is not empty"<<endl;
  84. }
  85. cout<<"The front now is "<<queue.Front() <<endl;
  86. cout<<"The rear now is "<<queue.Rear() <<endl;
  87. cout<<endl;
  88. //输入元素
  89. int times;
  90. cout<<"Please select the times you want to input"<<endl;
  91. cin>>times;
  92. int i=0;
  93. for(;i<times;i++){
  94. int value;
  95. cout<<"Please input your value"<<endl;
  96. cin>>value;
  97. int t=queue.enQueue(value);
  98. if(t==1){
  99. cout<<"Valid input"<<endl;
  100. }
  101. else{
  102. cout<<"Invalid input"<<endl;
  103. break;
  104. }
  105. }
  106. cout<<endl;
  107. //判断输入后的情况
  108. if(queue.isEmpty() ==1){
  109. cout<<"The current queue is empty"<<endl;
  110. }
  111. else{
  112. cout<<"The current queue is not empty"<<endl;
  113. }
  114. cout<<"The front now is "<<queue.Front() <<endl;
  115. cout<<"The rear now is "<<queue.Rear() <<endl;
  116. cout<<endl;
  117. //删除元素
  118. int dels;
  119. cout<<"Please select the times you want to delete"<<endl;
  120. cin>>dels;
  121. int ii=0;
  122. for(;ii<dels;ii++){
  123. int tt=queue.deQueue();
  124. if(tt==1){
  125. cout<<"Valid delete"<<endl;
  126. }
  127. else{
  128. cout<<"Invalid delete"<<endl;
  129. break;
  130. }
  131. }
  132. cout<<endl;
  133. //判断删除后的情况
  134. if(queue.isEmpty() ==1){
  135. cout<<"The current queue is empty"<<endl;
  136. }
  137. else{
  138. cout<<"The current queue is not empty"<<endl;
  139. }
  140. cout<<"The front now is "<<queue.Front() <<endl;
  141. cout<<"The rear now is "<<queue.Rear() <<endl;
  142. cout<<endl;
  143. return 0;
  144. }

结果展示:

2)请分析你程序中每个功能模块的算法时间复杂度。

构造循环队列,只需要设置队列长度为k+1并设置相应数组,同时初始头指针和尾指针为0即可。所以,时间复杂度为O(1)。

判断循环队列是否为空队列,只需要判断头指针是否与尾指针重合即可,即return(rear==front)。所以,时间复杂度为O(1)。

判断循环队列是否为空队列,只需要判断尾指针加一取余后是否与头指针重合即可,即return((rear+1)%size==front)。所以,时间复杂度为O(1)。

获取队首元素,只需要先判断循环队列是否为空队列,如果队列非空则直接返回头指针所对应的元素。所以,时间复杂度为O(1)。

获取队尾元素,只需要先判断循环队列是否为空队列,如果队列非空则直接返回尾指针所对应的元素。所以,时间复杂度为O(1)。

向循环队列插入一个元素,只需要先判断循环队列是否为满队列,如果队列非满则直接插入输入元素并重置尾指针。所以,时间复杂度为O(1)。

从循环队列中删除一个元素,只需要先判断循环队列是否为空队列,如果队列非空则直接改变头指针的位置,即可删除队首元素。所以,时间复杂度为O(1)。

 


其他:

  1. #include<stdlib.h>
  2. #include<iostream>
  3. using namespace std;
  4. #define SIZE 6
  5. #define Type char
  6. typedef struct{
  7. Type *elem;
  8. int front,rear,length;//注意,队列的所谓的指针不是指针,是int
  9. }Queue;
  10. bool isEmpty(Queue &Q)//: 检查循环队列是否为空。
  11. {
  12. if(Q.rear==Q.front)
  13. {
  14. return 1;
  15. }
  16. else
  17. {
  18. return 0;
  19. }
  20. }
  21. bool isFull(Queue &Q)//: 检查循环队列是否已满。
  22. {
  23. if((Q.rear+1)%Q.length==Q.front)
  24. {
  25. return true;
  26. }
  27. else
  28. {
  29. return false;
  30. }
  31. }
  32. void MyCircularQueue(Queue &Q,int k)//: 构造器,设置队列长度为 k 。
  33. {
  34. Q.length=k;
  35. Q.elem=new Type[Q.length];
  36. Q.front=Q.rear=0;
  37. cout<<"长度为k的队列构造完毕"<<endl;
  38. }
  39. int Front(Queue &Q,Type &e)//: 从队首获取元素。如果队列为空,返回 -1 。
  40. {
  41. if(isEmpty(Q))
  42. {
  43. cout<<"空队列"<<endl;
  44. return -1;
  45. }
  46. else
  47. {
  48. e=Q.elem[Q.front];
  49. cout<<"非空"<<endl;
  50. cout<<"队首元素"<<e<<"获取成功"<<endl;
  51. return 1;
  52. }
  53. }
  54. int Rear(Queue &Q,Type &e)//: 获取队尾元素。如果队列为空,返回 -1 。
  55. {
  56. if(isEmpty(Q))
  57. {
  58. cout<<"空队列"<<endl;
  59. return -1;
  60. }
  61. else
  62. {
  63. cout<<"非空"<<endl;
  64. if(Q.rear==0)
  65. {
  66. e=Q.elem[5];
  67. cout<<"队尾元素"<<e<<"获取成功"<<endl;
  68. return 1;
  69. }
  70. else
  71. {
  72. e=Q.elem[Q.rear-1];
  73. cout<<"队尾元素"<<e<<"获取成功"<<endl;
  74. return 1;
  75. }
  76. }
  77. }
  78. bool enQueue(Queue &Q,Type value)//: 向循环队列插入一个元素。如果成功插入则返回真。
  79. {
  80. if(!isFull(Q))
  81. {
  82. cout<<"非满"<<endl;
  83. Q.elem[Q.rear]=value;//因为初始front和rear都是0开头,所以与下标一致
  84. Q.rear=(1+Q.rear)%Q.length;
  85. cout<<value<<"已经插入"<<endl;
  86. return true;
  87. }
  88. else
  89. {
  90. cout<<"队列已满!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!"<<value<<"无法入队"<<endl;
  91. return false;
  92. }
  93. }
  94. int deQueue(Queue &Q,Type &e)//: 从循环队列中删除一个元素。如果成功删除则返回真。
  95. {
  96. if(isEmpty(Q))
  97. {
  98. cout<<"已空"<<endl;
  99. return -1;
  100. }
  101. else
  102. {
  103. cout<<"非空"<<endl;
  104. e=Q.elem[Q.front];
  105. Q.front=(Q.front+1)%Q.length;
  106. cout<<"删除了"<<e<<endl;
  107. return 1;
  108. }
  109. }
  110. int getlength(Queue &Q)
  111. {
  112. int len;
  113. len=(Q.rear-Q.front+Q.length)%Q.length;
  114. return len;
  115. }
  116. int main()
  117. {
  118. Queue a;
  119. Type temp;
  120. Type e[11]={'a','b','c','d','e','f','g','h','i','j','k'};
  121. int length=SIZE;
  122. MyCircularQueue(a,length);//初始化
  123. enQueue(a,e[0]);//入队,到第一次满
  124. enQueue(a,e[1]);
  125. enQueue(a,e[2]);
  126. enQueue(a,e[3]);
  127. enQueue(a,e[4]);
  128. if(isFull(a))//判断是否已满
  129. {
  130. cout<<"队列已满!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!"<<endl;
  131. }
  132. deQueue(a,temp);//删除队首
  133. Front(a,temp);//输出队首队尾元素
  134. Rear(a,temp);
  135. enQueue(a,e[5]);//插入两次,看看当队列已满,溢出时的效果 证明了程序在溢出时的插入无效
  136. enQueue(a,e[6]);//队列以满,试图插入的这个是g,查看满后队列是否可以阻止进入
  137. cout<<"该队列长度为"<<getlength(a)<<endl;
  138. Front(a,temp);//再次确定 1.队列确实是循环使用的,即0号位被再次利用 2.溢出的那一次插入无效
  139. Rear(a,temp);
  140. }

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

闽ICP备14008679号