循环队列的基本操作和简单实现

时光毁灭记忆、已成空白 提交于 2020-01-14 17:45:56

一、引入

队列的顺序表示和实现

队列的顺序表示-用一维数组base[MAXQSIZE]

#define MAXQSIZE 100	//最大队列长
typedef struct{
Qelem *base;		//初始化的动态分配存储空间
int front;		//头指针,不是指针变量,若队列不空,只想队头元素
int rear;		//尾指针,不是指针变量,若队列不空,指向队尾元素的下一个位置
}SqQueue;

初始:

front=rear=0;//队空

在这里插入图片描述
入队:

base[Q.rear]=e;//
rear++;	//指向下一空间

在这里插入图片描述
出队:

e=base[Q.front];//出队
front++;
front=rear;//队空标志

在这里插入图片描述
当rear==MAXQSIZE时,发生溢出
在这里插入图片描述

  • 若front=0,rear=MAXQSIZE时,再入队——真溢出;
  • 若front!=0,rear=MAXQSZIE时,再入队——假溢出

如何解决假溢出问题?

  1. 将队中元素向对头移动,缺点是浪费时间,队中元素都要移动
  2. 将队空间设想成一个循环的表,即分配给队列的m个存储单元可以循环使用,当rear = =MAXQSIZE时,若向量的开始端空着,又可从头使用空着的空间。当front= =MAXQSIZE时,也是一样的。

即引入循环队列
base[0]接在base[MAXQSIZE-1]之后,若rear+1MAXQSIZE,则令rear=0;
实现方法:利用
模(mod,即%)==求余运算。
插入元素:

Q.base[Q.rear]=e;	//把值赋给尾指针所指空间
Q.rear=(Q.rear+1)%MAXQSIZE;//尾指针更新,+1%MAX=0

删除元素:

e=Q.base[Q.front];//把头指针所指元素赋值给某个变量e
Q.front=(Q.front+1)%MAXQSIZE;//头指针位置的变化

循环队列并不是一个圈,是想象而成的。
所以,循环队列:循环使用为队列分配的存储空间。

判断队空队满:少用一个元素空间

  • 队空的条件:Q.front = Q.rear(队满也是,但无法区分,所以少用一个元素空间)
  • 队满的条件:(rear+1)%MAXQSIZE = Q.front
    在这里插入图片描述

二、循环队列基本操作

循环队列初始化

Status InitQueue(SqQueue &Q){
Q.base=new Qelemtype[MAXQSIZE]	//分配数组空间,base是首元素,是数组的地址,所以前面定义为指针变量,用C++语法简单
//C语法:用malloc函数
if(Q.base)
	exit(OVERFLOW);		//存储分配失败
Q.front=Q.rear=0;		//头尾指针置为0,队列为空
return OK;
}

循环队列的操作——求队列长度

int Qlength(SqQueue Q){
return ((Q.rear-Q.front+MAXQSIZE)%MAXQSIZE);

在这里插入图片描述循环队列入队

Status EnQueue(SqQueue &Q,int e){
if((Q.rear+1)%MAXQSIZE==Q.front)//队满
	return ERROR;
Q.base[Q.rear]=e; //把值赋给尾指针所指空间
Q.rear=(Q.rear+1)%MAXQSIZE;//尾指针更新,+1%MAX=0
return OK;

循环队列出队

Status DeQueue(SqQueue &Q,int &e){
if(Q.front==Q.rear)	//队空
	return ERROR;
e=Q.base[Q.front];	//保存队头元素	
Q.front=(Q.front+1)%MAXQSIZE;	//队头指针+1
return OK;
}

循环队列取队头元素

int GetHead(SqQueue Q){
if(Q.front!=Q.rear)	//队列不为空
	return Q.base[Q.front];	//返回队头指针元素的值,队头指针不变

三、循环队列简单实现

#include<bits/stdc++.h>
using namespace std;
const int MAXQSIZE=10;
typedef struct{
 int *base;
 int front;
 int rear;
}SqQueue;

bool InitQueue(SqQueue &Q){
 Q.base=new int[MAXQSIZE];
 if(!Q.base)
  exit(false);
 Q.front=Q.rear=0;
 return true;
}

int Qlength(SqQueue Q){
return ((Q.rear-Q.front+MAXQSIZE)%MAXQSIZE);
}

bool EnQueue(SqQueue &Q,int e){
if((Q.rear+1)%MAXQSIZE==Q.front)//队满
 return false;
Q.base[Q.rear]=e; //把值赋给尾指针所指空间
Q.rear=(Q.rear+1)%MAXQSIZE;//尾指针更新,+1%MAX=0
return true;
}

bool DeQueue(SqQueue &Q,int &e){
if(Q.front==Q.rear) //队空
 return false;
e=Q.base[Q.front]; //保存队头元素 
Q.front=(Q.front+1)%MAXQSIZE; //队头指针+1
return true;
}

int GetHead(SqQueue Q){
if(Q.front!=Q.rear) //队列不为空
 return Q.base[Q.front]; //返回队头指针元素的值,队头指针不变
}

int main()
{
 int n;
 SqQueue Q;
 cout<<"循环队列基本操作:"
	   <<"1、循环队列初始化\n"
	   <<"2、入队\n" 
	   <<"3、求队列长度\n"
	   <<"4、取队头元素\n"
	   <<"5、出队\n" ;
 while(1){
	
	  cout<<"输入操作序号:";
	  cin>>n; 
	  switch(n)
	  {
	   case 1: if(InitQueue (Q))
	      cout<<"循环队列初始化成功"<<endl;
	     else 
	      cout<<"初始化失败";
	     break; 
	   case 2:
	     for(int i=0;i<=10;i++)
	       EnQueue(Q,i);
	     cout<<"入队成功"<<endl; break;      
	   case 3:
	      cout<<"队列长度为"<<Qlength(Q)<<endl; break;//输出是9,因为队尾指针一开始变为1
	   case 4:
	     cout<<" 队头元素为:"<<GetHead(Q)<<endl;break; 
	   case 5:
	     
	     cout<<"出队,队列元素为:";
	     for(int i=0;i<10;i++)
	     {
	      DeQueue(Q,i);
	      cout<<i<<" ";
	  }
	     cout<<endl;break;  
	}
 }
}

内容参考:
《数据结构》严蔚敏
青岛大学——王卓

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!