循环队列的成因及其基本操作

本以为循环队列是个高级操作,后来发现是个必备操作,不然太浪费地儿了
解释如下
还是先介绍下队列的顺序存储结构

typedef struct
{
    
    
	int *base;
	int front;
	int rear;
}sqqueue;

来,和栈的顺序存储结构比较一下

typedef struct
{
    
    
	int *base;
	int *top;
	int stacksize;
}

栈的栈底是不动的,所以可用base来指向栈的首地址,top上下移动,就像一个注射器一样.
队列首尾都要变,所以要另设一个base来记录队列地址,另设两个指针front,rear(感觉都不能算准确的指针,就是记住首尾的数组下标)
接下来解释下为什么是循环队列,上图
在这里插入图片描述
控制面板真心不好写字…
如图,队列放入了6个元素,然后又删除了3个元素,那如果让你继续放元素呢,放不下了!可是还有一半的空间没用呢,为了避免这种极度浪费,人们想出了循环队列. 逻辑上,让队列的首尾连接起来.

即上图再放如a7时,就让a7放到a1的位置,这有点像数学里面的周期函数,f(1)=f(T+1),这里的T就等于6,其实就是队列的最大容量.

但是这样的话,你无法判断队列满了没有,因为尾指针总在最后一个元素的上一位,这样的话,队列满时的条件Q.rear==Q.front和空队时是一模一样的.

解决办法之一就是少用一个空间,当队列还有一个空间没用时就判断队列已满,即 (Q.rear+1)%maxsize==Q.front (Q.front也要进行%maxsize的处理,只不过是在后面) 这样,就和空队列的判断不一样了.

高中我们经常写周期函数的题,自变量X除以周期T,余几,就是f几.

循环队列是一个道理,它们又有点像两个小孩在田径场的圆圈跑道上跑步,同一起跑线出发,后出发的小孩一直追着先出发的小孩跑,永远无法超过.当先出发的小孩比后出发的小孩多跑了快一圈时,游戏就结束了,即队列满了.

下面上队列的基本操作:

1.循环队列的初始化

2.求循环队列的长度

3.循环队列的入队

4.循环队列的出队

5.取循环队列的队头元素

开始开始

1.循环队列的初始化

#define overflow -2
#define maxsize 100
int initqueue(sqqueue &Q)
{
    
    
	Q.base=new int[maxsize]; //为队列分配一个最大容量为maxsize的空间
	if(!Q.base)exit(overflow);  //存储分配失败
	Q.front=Q.rear=0;       //头指针和尾指针置为0,队列为空
}

2.求队列长度

int queuelength(sqqueue Q)
{
    
    
return (Q.rear+maxsize-Q.front)%maxsize;
}

括号里面加maxsize是为了避免Q.rear-Q.front为负数

3.循环队列的入队

int enqueue(sqqueue &Q,int e)
{
    
    
	if((Q.rear+1)%maxsize==Q.front) //队满,无法再放入
	return error;
	Q.base[Q.rear]=e;  //新元素插入队尾
	Q.rear=(Q.rear+1)%maxsize;  //队尾指针加一
}

4.循环队列的出队

int dequeue(sqqueue &Q,int &e)
{
    
    
	if(Q.rear==Q.front) //队空,没法出
	return error;  
	e=Q.base[Q.front];  //保存队头元素
	Q.front=(Q.front+1)%maxsize;  //队头指针加一
}

5.取队头元素

int gethead(sqqueue Q)
{
    
    //返回Q的队头元素,不修改队头指针
if(Q.rear!=Q.front)
return Q.base.[Q.front];
}

That’s all.Thank you.

Guess you like

Origin blog.csdn.net/heipao17/article/details/115272471