队列这种结构再生活中非常常见,从队尾入队,队头出队,利用顺序表来制作一个队列存在一个“假溢出"问题。
什么是假溢出?
当我们用一个数组的开头元素作为队头,而最后一个元素作为队尾;假设在这时整个数组都填满了,然后从这个数组中抽出几个元素,队列的开头其实是空的,但由于尾部已经满了,所以看起来好像整个队列已经”满“了,但是我们都很清楚,在队伍的开头出还有空位,为了解决这个问题,我们采用了一种循环结构的队列。当队尾满时会自动检查队伍前面是否由空位。
由于在使循环队列时,当队头位标等于队尾位标时存在俩种情况,一种是队列是空的,而另外一种可能时队列是满的。
所以我们将队列的一位空出来不去使用,这样就能区分队列到底是空还是满。
下面是队列的结构声明:
typedef int ElemType;
typedef struct{
ElemType data[MAXSIZE];
int front;
int rear;
}SqQueue;
以Q作为队列结构为例,
计算队列长度的公式 : (rear - front + MAXSIZE) % MAXSIZE
判断队列是否为满的条件:(rear + 1) % MAXSIZE == front
判断队列是否为空的条件: rear == front.
下面是各个操作。
初始化操作:
void initQueue(SqQueue *Q){
/* 这个函数用来初始化顺序队列*/
if(Q == NULL){
printf("空指针无法初始化!!\n");
}
else{
Q->front = 0;
Q->rear = 0;
printf("队列初始化成功!!\n");
}
}
计算队列长度的操作:
int QueueLength(SqQueue *Q){
/*这个函数用来计算队列的长度*/
return ((Q->rear - Q->front + MAXSIZE) % MAXSIZE);
}
入队操作:
void EnQueue(SqQueue *Q, ElemType e){
/*这个函数用来向队列中插入元素*/
if((Q->rear + 1) % MAXSIZE == Q->front){
printf("该队列已满,无法再向其中添加元素!!\n");
}else{
Q->data[Q->rear] = e;
Q->rear = (Q->rear + 1) % MAXSIZE;
printf("该数据成功插入队列!!\n");
}
}
出队操作:
void DeQueue(SqQueue *Q, ElemType *e){
/* 这个函数用来删除队列中的队头元素*/
if(Q->front == Q->rear){
printf("该队列是空的,没有可以出队的元素!!\n");
} else{
*e = Q->data[Q->front];
Q->front = (Q->front + 1) % MAXSIZE;
printf("该元素成功清出队列!!\n");
}
}
打印队列操作:
void PrintQueue(SqQueue *Q){
/* 这个函数用来打印队列中的内容*/
if(Q->front == Q->rear){
printf("该队列是空的!!\n");
}else{
if(Q->rear > Q->front){
int index;
for(index = Q->front; index < Q->rear; index++){
printf("%d ",Q->data[index]);
}
printf("\n");
}else{
int index = Q->front;
while((index % MAXSIZE) != Q->rear){
printf("%d ", Q->data[index]);
index = (index + 1) % 5;
}
printf("\n");
}
}
}