1、分析
循环队列最主要的特点为当前面的空间被pop后,后面的数据可以插入到前面空余的数据中去;
所以最难的部分为判断什么时候为空什么时候为满:
a、空满问题
我们先来分析当数据满时,head和tail相等(tail认为是指向队尾的下一个空间,因为书写起来比较容易)。
、
那么什么时候为满呢?
b、空满问题解决
显然当tail和head相等时为满,那么这就会导致逻辑混乱。解决方法有以下两种:
法一:增加一个size变量用来记录队列大小,0为空,满为等于申请的空间值;
法二:额外开一个空间;
所以当head==tail+1%k时空间为满,head==tail时为空(k为给定的k+1)
本人采用第二种方法(为了保证tail和head的有效性时我们会给其%k)
c、tail为0时的插入数据
所以当tail为0时插到k的位置。
或者直接用这个公式:(这个时力扣官方给出的结果)
obj->elements[(obj->rear - 1 + obj->capacity) % obj->capacity]
2、实现
typedef struct {int* a;int head;int tail;int k;} MyCircularQueue;MyCircularQueue* myCircularQueueCreate(int k) {MyCircularQueue*mq =(MyCircularQueue*)malloc(sizeof(MyCircularQueue));mq->a=(int*)malloc((k+1)*sizeof(int));mq->head=mq->tail=0;mq->k=k+1;return mq;
}bool myCircularQueueEnQueue(MyCircularQueue* obj, int value) {if((obj->tail+1)%obj->k==obj->head){return false;}obj->a[obj->tail]=value;obj->tail=(obj->tail+1)%obj->k;return true;
}bool myCircularQueueDeQueue(MyCircularQueue* obj) {if(obj->tail==obj->head){return false;}obj->head=(obj->head+1)%(obj->k);return true;
}int myCircularQueueFront(MyCircularQueue* obj)
{if(obj->tail==obj->head){return -1;} return obj->a[obj->head];
}int myCircularQueueRear(MyCircularQueue* obj) {if(obj->head==obj->tail){return -1;}return obj->a[(obj->tail-1+obj->k)%obj->k];
}bool myCircularQueueIsEmpty(MyCircularQueue* obj) {return (obj->head)==(obj->tail);
}bool myCircularQueueIsFull(MyCircularQueue* obj) {return (obj->head)==(obj->tail+1)%(obj->k);
}void myCircularQueueFree(MyCircularQueue* obj) {free(obj->a);free(obj);
}/*** Your MyCircularQueue struct will be instantiated and called as such:* MyCircularQueue* obj = myCircularQueueCreate(k);* bool param_1 = myCircularQueueEnQueue(obj, value);* bool param_2 = myCircularQueueDeQueue(obj);* int param_3 = myCircularQueueFront(obj);* int param_4 = myCircularQueueRear(obj);* bool param_5 = myCircularQueueIsEmpty(obj);* bool param_6 = myCircularQueueIsFull(obj);* myCircularQueueFree(obj);
*/