在普通的队列中很容易出现假溢出的情况,为了防止假溢出,就会有循环队列。循环队列最显眼的特征就是有一个%操作,下面就以书上的常用操作集合,并给出完整的测试样例。
1、循环队列顺序存储结构
在循环队列的顺序存储的时候,基地址是一个指针可以动态分配内存,并且有头指针和尾指针。
typedef struct{
QElemType *base;//动态分配存储空间
int front;//头指针,若队列不空,指向队头元素
int rear;//尾指针,若队列不空,指向队尾元素的下一个位置
}SqQueue;
2、初始化队列
初始化队列步骤如下:
- 分配内存,并检验内存分配是否成功?
- 头指针与尾巴指针都为0,
- 返回OK
Status InitQueue(SqQueue &Q){
Q.base = new QElemType[MAXQSIZE];//分配数组空间
//Q.base = (QElemType*)malloc(MAXQSIZE*sizeof(QElemType));
if(!Q.base) exit(OVERFLOW);//存储分配失败
Q.front = Q.rear = 0;//头指针尾指针置为0,队列为空
return OK;
}
3、判定队列是否为空
头指针与尾巴指针同时指向是否为0,
Status IsEmpty(SqQueue Q){
if(Q.front == Q.rear) return TRUE;
else return FALSE;
}
4、判定队列是否满了
在循环队列中,判定是否满了,就是尾指针加1与队列的容量取模,如果与头指针相等那么就满了
Status IsFull(SqQueue Q){
if((Q.rear+1)%MAXQSIZE == Q.front) return TRUE;
else return FALSE;
}
5、入队
入队首先判定队列是否满了,满了返回error,入队在队尾,所以是rear
- 判定是否满了
- 队尾赋值
- 队尾指针++
Status EnQueue(SqQueue &Q,QElemType e){
if(IsFull(Q)) return ERROR; //队列满
Q.base[Q.rear] = e;
Q.rear = (Q.rear+1)%MAXQSIZE;
return OK;
}
6、出队
出队的话,是队头出队,所以要判定队是否空。
Status DeQueue(SqQueue &Q,QElemType &e){
if(IsEmpty(Q)) return ERROR;//队空
e = Q.base[Q.front]; //保存队头元素
Q.front = (Q.front+1)%MAXQSIZE;//队头指针+1
return OK;
}
7、求队列的长度
尾指针与头指针的差值
int QueueLength(SqQueue Q){
return (Q.rear-Q.front+MAXQSIZE)%MAXQSIZE;
}
8、获得队列的首元素
在判断队列是否为空的前提下,front返回出去,
QElemType GetHead(SqQueue Q){
if(!IsEmpty(Q)){
//队列不为空
return Q.base[Q.front];//返回队头指针元素的值,队头指针不变。
}
}
测试效果
完整代码
#include<iostream>
#define TRUE 1
#define FALSE 0
#define OK 1
#define ERROR 0
#define OVERFLOW -1
#define MAXQSIZE 10
using namespace std;
typedef int Status;
typedef int QElemType;
typedef struct{
QElemType *base;//动态分配存储空间
int front;//头指针,若队列不空,指向队头元素
int rear;//尾指针,若队列不空,指向队尾元素的下一个位置
}SqQueue;
//队列初始化
Status InitQueue(SqQueue &Q){
Q.base = new QElemType[MAXQSIZE];//分配数组空间
//Q.base = (QElemType*)malloc(MAXQSIZE*sizeof(QElemType));
if(!Q.base) exit(OVERFLOW);//存储分配失败
Q.front = Q.rear = 0;//头指针尾指针置为0,队列为空
return OK;
}
int QueueLength(SqQueue Q){
return (Q.rear-Q.front+MAXQSIZE)%MAXQSIZE;
}
//队列判定是否为空
Status IsEmpty(SqQueue Q){
if(Q.front == Q.rear) return TRUE;
else return FALSE;
}
//队列判定是否满
Status IsFull(SqQueue Q){
if((Q.rear+1)%MAXQSIZE == Q.front) return TRUE;
else return FALSE;
}
//入队循环队列入队
Status EnQueue(SqQueue &Q,QElemType e){
if(IsFull(Q)) return ERROR; //队列满
Q.base[Q.rear] = e;
Q.rear = (Q.rear+1)%MAXQSIZE;
return OK;
}
//base[0]接在base[MAXQSIZE-1]之后,若rear+1==M,则令rear=0
Status DeQueue(SqQueue &Q,QElemType &e){
if(IsEmpty(Q)) return ERROR;//队空
e = Q.base[Q.front]; //保存队头元素
Q.front = (Q.front+1)%MAXQSIZE;//队头指针+1
return OK;
}
//取队头元素
QElemType GetHead(SqQueue Q){
if(!IsEmpty(Q)){
//队列不为空
return Q.base[Q.front];//返回队头指针元素的值,队头指针不变。
}
}
int main(){
SqQueue Q;
InitQueue(Q);
cout << "after init,Is Queue empty? 1 represent yes:" << IsEmpty(Q) << endl;
for(int i=0;i<5;i++){
EnQueue(Q,i+1);
}
cout << "queue length:" << QueueLength(Q) << endl;
cout << "After enqueue,Is Queue full?1 represent yes:" << IsFull(Q) << endl;
cout << "get queue head value: " << GetHead(Q) << endl;
QElemType e;
DeQueue(Q,e);
cout << "delete 1 queue value: " << e << endl;
cout << "queue length:" << QueueLength(Q) << endl;
return 0;
}