今天看图的广度优先遍历的时候,发现用到了循环队列,补一下循环队列的知识,参考《大话数据结构》的P116~117,自己写了一个简单的测试例子便于理解。
首先需要理解以下三条公式。
front是队头元素的下标,rear是队尾元素后一位的下标。(书上用头指针和尾指针,front和rear并不是指针,个人觉得不太好)
1、队列空的条件
显然front==rear
注意:如果队列不保留任何元素空间
满足front==rear的情况下,可能是队列空,也可能是队列满。所以为了方便,本文讨论的是采用保留一个元素空间的方法。(也可以采用设置标志变量的方法)
2、队列满的条件
队列满只有这两种情况,所以队列满的条件是:
(rear+1)%QueueSize==front
3、队列长度计算公式
同时考虑这两种情况,队列计算公式是:
rear-front+MAXSIZE)%MAXSIZE
MAXSIZE是队列长度(包括那个保留的元素空间)
下面举个简单的例子,实现循环队列的创建,入队和出队操作。
代码和解释如下(Qt Creator测试通过):
1 #include <iostream> 2 #include <string> 3 using namespace std; 4 5 #define MAXSIZE 5 6 7 //循环队列的顺序存储结构 8 typedef struct 9 { 10 char data[MAXSIZE];//队列,用数组形式表示,这里假设最多只有4个元素 11 //保留一个元素空间,否则front==rear,是空队列还是满队列不容易判断 12 int front;//头序号,第一个元素的下标 13 int rear;//尾序号,最后一个元素的下标 14 }SqQueue; 15 16 //循环队列的初始化,返回指向循环队列的地址 17 SqQueue *InitQueue(SqQueue *Q) 18 { 19 Q=new SqQueue; 20 Q->front=0; 21 Q->rear=0;//初始化为空队列(front==rear为空队列) 22 return Q; 23 } 24 25 //求循环队列的长度,返回循环队列的当前长度 26 int QueueLength(SqQueue *Q) 27 { 28 return (Q->rear-Q->front+MAXSIZE)%MAXSIZE; 29 } 30 31 //循环队列的入队列操作 32 void EnQueue(SqQueue *Q,char e) 33 { 34 if((Q->rear+1)%MAXSIZE==Q->front)//判断循环队列是否满 35 { 36 cout<<"error"<<" "; 37 return; 38 } 39 Q->data[Q->rear]=e;//将元素e插入队尾 40 Q->rear=(Q->rear+1)%MAXSIZE;//尾序号rear加1,若到最后转向头部 41 cout<<"ok"<<" "; 42 return; 43 } 44 45 //循环队列的出队列操作 46 char DeQueue(SqQueue *Q) 47 { 48 char e; 49 if(Q->front==Q->rear)//如果队列是否空 50 { 51 cout<<"error"<<" "; 52 return 0;//返回0表示队列空,没有出队元素 53 } 54 e=Q->data[Q->front]; 55 Q->front=(Q->front+1)%MAXSIZE;//头序号front加1,若到最后转向头部 56 cout<<"ok"<<" "<<e<<endl; 57 return e; 58 } 59 60 int main(void) 61 { 62 SqQueue *s=NULL; 63 64 //初始化一个空队列s 65 s=InitQueue(s); 66 67 //插入元素,并返回当前队列长度 68 EnQueue(s,‘A‘);//插入A 69 cout<<s->data[0]<<" ";//提示队尾是否插入A(因为初始化时rear=0,所以从下标为0的地方开始插入) 70 cout<<QueueLength(s)<<endl;//输出当前长度1 71 72 EnQueue(s,‘B‘);//插入B 73 cout<<s->data[1]<<" ";//提示队尾是否插入B 74 cout<<QueueLength(s)<<endl;//输出当前长度2 75 76 EnQueue(s,‘C‘);//插入C 77 cout<<s->data[2]<<" ";//提示队尾是否插入C成功 78 cout<<QueueLength(s)<<endl;//输出当前长度3 79 80 EnQueue(s,‘D‘);//插入D 81 cout<<s->data[3]<<" ";//提示队尾是否插入D成功 82 cout<<QueueLength(s)<<endl;//输出当前长度4 83 84 EnQueue(s,‘E‘);//插入E,输出error,说明插入失败 85 cout<<QueueLength(s)<<endl;//输出当前长度4,说明已经满了不能再插入 86 87 //出队 88 DeQueue(s);//输出A 89 DeQueue(s);//输出B 90 91 //再插入元素,理解队列的循环 92 EnQueue(s,‘E‘);//插入E 93 cout<<s->data[4]<<" "<<s->rear<<endl;//提示队尾是否插入E成功,这时候rear挪到下标0的地方了 94 EnQueue(s,‘F‘);//插入F 95 cout<<s->data[0]<<" "<<s->rear<<endl;//提示队尾是否插入F成功,这时候rear挪到下标1的地方了 96 EnQueue(s,‘G‘);//插入G,输出error,说明插入失败 97 cout<<QueueLength(s)<<endl;//输出当前长度4,说明已经满了不能再插入 98 }
运行结果:
时间: 2024-09-28 18:00:19