数据结构与算法分析—循环队列的数组实现(C语言)
队列,也是一种表,使用队列的时候在表的末端队尾插入元素,在表的开头删除元素,因为先插入的元素先被访问,故队列又称为先进先出表,其基本操作为进队与出队,对应着插入与删除,也要先进行相应的判空判满
队列可以用链表实现,也可以用数组实现,这里用数组实现,每一个队列都有Fron和Rear来指向队头和队尾,我这里实现的是循环队列,值得注意的是何时为满,何时为空,如果Front与Rear同时指向一个位置为空,但是我们发现队列满的时候Front与Rear也同时指向同一个位置,这是为什么呢,举个例子,一个能存储6个元素的队列,队列总共有0,1,2,3,4,5,6种状态,而Front与Rear的差值只有0,1,2.,3,4,5种状态,根本不可能用5种状态来表示6种状态,有两种解决的方法,用一个Size变量来记录队列里元素的多少。或者用一个tag,删除的时候标记为1,插入的时候标记为0,当Front与Rear相等时判断即可。另外一种方法就是我们用n-1个空间,代码用第二种方法实现
之前做PTA上的题,有道题为Deque双端队列,把栈 链表 队列的知识综合在一起了,挺不错的。
#include<stdio.h>
#include<stdlib.h>
struct QueueRecord;
typedef struct QueueRecord* Queue;
typedef int ElementType;
struct QueueRecord{
int Capacity;
int Front;
int Rear;
ElementType *Array;
};
int IsEmpty(Queue Q);
int IsFull(Queue Q);
Queue CreateQueue(int MaxElements);
void DisposeQueue(Queue Q);
void MakeEmpty(Queue Q);
void Enqueue(ElementType X,Queue Q);
int Dequeue(Queue Q);
//判断是否为空队列
int IsEmpty(Queue Q){
return Q->Front==Q->Rear;
}
//判断队列是否为满队列
int IsFull(Queue Q){
return ((Q->Rear+1)%Q->Capacity==Q->Front);
}
//初始化一个队列
Queue CreateQueue(int MaxElements){
Queue Q=(Queue)malloc(sizeof(struct QueueRecord));
Q->Array=(ElementType*)malloc(sizeof(ElementType)*MaxElements);
Q->Capacity=MaxElements;
MakeEmpty(Q);
return Q;
}
//让队列为空
void MakeEmpty(Queue Q){
Q->Front=Q->Rear=0;
}
//删除一个队列
void DisposeQueue(Queue Q){
if(Q!=NULL){
free(Q->Array);
free(Q);
}
}
//向队列末尾里添加元素
void Enqueue(ElementType X,Queue Q){
if(IsFull(Q)){
printf("队列已满\n");
}else{
Q->Rear=(Q->Rear+1)%Q->Capacity;
Q->Array[Q->Rear]=X;
}
}
//删除队列头部元素并返回
int Dequeue(Queue Q){
if(IsEmpty(Q)){
printf("队列为空\n");
return 0;
}else{
Q->Front=(Q->Front+1)%Q->Capacity;
return Q->Array[Q->Front];
}
}
int main(void){
Queue Q;
Q=CreateQueue(5);
for(int i=1;i<=4;i++){
Enqueue(i,Q);
}
if(IsFull(Q)){
printf("满\n");
}
for(int i=1;i<=4;i++){
printf("%d\n",Dequeue(Q));
}
if(IsEmpty(Q)){
printf("空\n");
}
return 0;
}