队列的顺序存储结构,是将元素存在一个一维数组中,队头所在的位置下标是0,当要入队操作时,直接在队尾后一个位置插入一个结点即可,时间复杂度为O(1)。而出队列,出队的元素下标为0,所以队列中所有的元素都要向前移动,时间复杂度为O(n)。如果不去限制队头的元素必须存在下标为0的位置,那么也可以做到时间复杂度为O(1)。为了避免只有一个元素时,队头队尾重合使得处理变得麻烦,于是设置两个指针,front指向队头元素,rear指向队尾下一个位置,当front==rear时,表示空队列。但是假设,rear==MAXSIZE,而front!=0,也就是指下标为0—front的位置没有元素,而front—-MAXSIZE-1的位置已经有元素了,如果此时,继续入队,就会出现数组越界的错误,实际上队列在下标为0-front的位置还是空的,这种现象叫假溢出。解决假溢出的办法就是当后面满了。rear就从头开始,也就是头尾相连的循环队列。
循环队列判断空队列方式是front==rear,而当队列满的时候也是front==rear,那么要如何判断队空,还是满呢?
我们修改判断队满的条件,保留一个元素空间,也就是说当队列满时,数组中还有一个位置空着。所以判断队列满的条件就是:(rear+1)%MAXSIZE==front,计算队列长度公式为:(rear-front+MAXSIZE)%MAXSZIE
代码如下:
#include "iostream"
using namespace std;
#define OK 1
#define ERROR 0
#define MAXSIZE 100
typedef int Status;
typedef int ElemType ;
//循环链表的存储结构
typedef struct
{
ElemType data[MAXSIZE];
int front;//front指向队头元素
int rear;//rear指向队尾元素后一个节点
//空队列的判别条件 是 front==rear;
//队列满的条件是(rear+1)%MAXSIZE==front
//队列的从长度为(rear-front+MAXSIZE)%MAXSIZE
}SqQueue;
//初始化队列。
Status InitQueue(SqQueue &Q)
{
Q.front = Q.rear = 0;//空队列
return OK;
}
//获取队列长度,即队列中元素个数
Status QueueLength(SqQueue Q)
{
return (Q.rear - Q.front + MAXSIZE) % MAXSIZE;
}
//插入元素
Status InsertQueue(SqQueue &Q, ElemType e)
{
if ((Q.rear + 1) % MAXSIZE == Q.front) return ERROR;//判断队满
Q.data[Q.rear] = e;
Q.rear=(Q.rear+1)%MAXSIZE;//尾指针后移一位
return OK;
}
//删除元素
Status DeleteQueue(SqQueue &Q, ElemType &e)
{
if (Q.rear == Q.front) return ERROR;//判断队空
e = Q.data[Q.front];
Q.front = (Q.front + 1) % MAXSIZE;//头指针后移一位
return OK;
}
Status Visit(SqQueue Q)
{
if (Q.rear == Q.front)
{
cout << "空队列" << endl;
return ERROR;
}
int i = Q.front;
while (i!=Q.rear)
{
cout << Q.data[i] << " ";
i = (i + 1) % MAXSIZE;
}
cout << endl;
return OK;
}
int main()
{
SqQueue Q;
InitQueue(Q);
InsertQueue(Q, 1);
InsertQueue(Q, 3);
InsertQueue(Q, 5);
InsertQueue(Q, 7);
InsertQueue(Q, 9);
Visit(Q);
int e;
DeleteQueue(Q, e);
InsertQueue(Q, 11);
Visit(Q);
getchar();
return 0;
}
运行结果: