- 设计循环队列- LeetCode题目链接
- 提示
循环队列可以用链表实现也可以用数组实现,这里使用数组实现。
- 思路
循环队列的判满是比较关键的地方,没有判空那么简单,因为back == front分辨不出是满还是空,所以判满这里使用多开辟一个空间的方法。在尾部多开辟一个空间,其位置不存储数据,可以实现判满,实际还是存储一样的数据量。
- 举例
如图已经插入四个数据,即队列已满
当我们删除了1,并且插入5后:
- 代码实现
typedef struct {
int* a;
int front;
int N;
int back;
} MyCircularQueue;
MyCircularQueue* myCircularQueueCreate(int k) {
MyCircularQueue* obj = (MyCircularQueue*)malloc(sizeof(MyCircularQueue));
obj->a = (int*)malloc(sizeof(int)*(k+1));
//额外开多一个空间
//仍然只存储k个数据,但是数组长度为N,可以更好地判队列满
obj->front = obj->back = 0;
obj->N = k+1;
return obj;
}
bool myCircularQueueIsEmpty(MyCircularQueue* obj) {
//头尾相等判空
return obj->front == obj->back;
}
bool myCircularQueueIsFull(MyCircularQueue* obj) {
//判满
return (obj->back+1)%obj->N == obj->front;
}
//插入数据
bool myCircularQueueEnQueue(MyCircularQueue* obj, int value) {
if(myCircularQueueIsFull(obj))
return false;
obj->a[obj->back] = value;
obj->back++;
//如果到达尾,让back回到起点
obj->back %= obj->N;
return true;
}
//删除数据
bool myCircularQueueDeQueue(MyCircularQueue* obj) {
if(myCircularQueueIsEmpty(obj))
return false;
//删数据不用清除,只要把头指针移走即可
obj->front++;
//如果到达尾,让front回到起点
obj->front %= obj->N;
return true;
}
//返回队头元素
int myCircularQueueFront(MyCircularQueue* obj) {
if(myCircularQueueIsEmpty(obj))
return -1;
else
return obj->a[obj->front];
}
int myCircularQueueRear(MyCircularQueue* obj) {
// 法一:
// if(myCircularQueueIsEmpty(obj))
// return -1;
// //不要直接返回back-1位置,因为back处于下标0位置有bug
// else if(obj->back == 0)
// return obj->a[obj->N];
// else
// return obj->a[obj->back-1];
// 法二:
if(myCircularQueueIsEmpty(obj))
return -1;
else
//只要back+1没达到5,都不受%5的影响
//front在前back在后
//back在前front在后
return obj->a[(obj->back-1 + obj->N) % obj->N];
}
void myCircularQueueFree(MyCircularQueue* obj) {
free(obj->a);
free(obj);
}