1、题意描述
2、思路分析(数组)
在循环队列中,队列长度是固定的,所以可以利用数组来创建队列。
假设队列有4个元素,利用front指向首元素,rear指向末尾元素,会发现当队列中没有元素时和队列中只有一个元素时的情况是一样的
此时自然而然可以想到让rear指向末尾的下一个元素,但这样,队列为空和队列满了的情况是一样的
此时可以将队列的长度设置成k+1,front指向队首元素,rear指向队尾元素的下一个,这样子无论是说明情况,当front==rear时就是队列是空的,当(rear+1)%k==front时是队列满了
此时再连续出队列4次,即front向前移动4次,仍然满足front==rear
3、代码实现
1、循环队列的创建和初始化
typedef struct {
int* a;
int front;
int rear;
int capacity;
} MyCircularQueue;
MyCircularQueue* myCircularQueueCreate(int k) {
MyCircularQueue* obj = (MyCircularQueue*)malloc(sizeof(MyCircularQueue));
obj->front=obj->rear=0;//front是第一个元素的下标,rear是最后一个元素的下一个
obj->capacity=k+1;//要存放比k多一个元素
obj->a=(int*)malloc(sizeof(int)*(k+1));
return obj;
}
2、向循环队列中插入元素
首先,需要判断循环队列是否满了,如果满了就返回false,如果没有满,则rear的位置放入要插入的元素,然后更新rear,注意此时的rear并不是简单的向后移动
此时若向队列中插入3,然后rear++,那么rear将会超出数组的范围,因为是循环队列,rear是可以到前面去的,所以在插入后要更新rear之前,需要先判断一下rear+1是不是会超过了k,如果超过了k,就让rear指向前面
bool myCircularQueueEnQueue(MyCircularQueue* obj, int value) {
if((obj->rear+1)%obj->capacity==obj->front)
return false;
obj->a[obj->rear]=value;
obj->rear=(obj->rear+1)%obj->capacity;
return true;
}
3、从循环队列中删除一个元素
首先,需要判断队列是否为空,如果为空,直接返回false,如果不为空,就将front++,然后更新front,与上面相同,仍然需要判断front是否会超出数组的范围,如果超出则要让front到前面去
bool myCircularQueueDeQueue(MyCircularQueue* obj) {
if(obj->front==obj->rear)
return false;
obj->front=(obj->front+1)%obj->capacity;
return true;
}
4、返回队列首元素
int myCircularQueueFront(MyCircularQueue* obj) {
if(obj->front==obj->rear)
return -1;
return obj->a[obj->front];
}
5、返回队列末尾元素(重点)
因为在创建循环队列时,rear指向的是队列末尾元素的下一个,所以很容易想到直接返回rear-1指向的元素即可,但是并不是这样子的
像这样子普通的当然可以,但是当rear指向的是数组中下标为0的元素时就不行了,因为数组下标没有负数
所以可以直接将rear-1+k再去%k
int myCircularQueueRear(MyCircularQueue* obj) {
if(obj->front==obj->rear)
return -1;
return obj->a[(obj->rear-1+obj->capacity)%obj->capacity];
}
6、判断队列是否为空
由前面分析可知,当front==rear时为空
bool myCircularQueueIsEmpty(MyCircularQueue* obj) {
return obj->front==obj->rear;
}
7、判断队列是否满了
有全面分析可知,当(rear+1)%k==front时就是满了
bool myCircularQueueIsFull(MyCircularQueue* obj) {
return (obj->rear+1)%obj->capacity==obj->front;
}
8、销毁循环队列
void myCircularQueueFree(MyCircularQueue* obj) {
free(obj->a);
free(obj);
}