题目
设计你的循环队列实现。 循环队列是一种线性数据结构,其操作表现基于 FIFO(先进先出)原则并且队尾被连接在队首之后以形成一个循环。它也被称为“环形缓冲器”。 循环队列的一个好处是我们可以利用这个队列之前用过的空间。在一个普通队列里,一旦一个队列满了,我们就不能插入下一个元素,即使在队列前面仍有空间。但是使用循环队列,我们能使用这些空间去存储新的值。 你的实现应该支持如下操作: MyCircularQueue(k): 构造器,设置队列长度为 k 。 Front: 从队首获取元素。如果队列为空,返回 -1 。 Rear: 获取队尾元素。如果队列为空,返回 -1 。 enQueue(value): 向循环队列插入一个元素。如果成功插入则返回真。 deQueue(): 从循环队列中删除一个元素。如果成功删除则返回真。 isEmpty(): 检查循环队列是否为空。 isFull(): 检查循环队列是否已满。
示例: MyCircularQueue circularQueue = new MyCircularQueue(3); // 设置长度为 3 circularQueue.enQueue(1); // 返回 true circularQueue.enQueue(2); // 返回 true circularQueue.enQueue(3); // 返回 true circularQueue.enQueue(4); // 返回 false,队列已满 circularQueue.Rear(); // 返回 3 circularQueue.isFull(); // 返回 true circularQueue.deQueue(); // 返回 true circularQueue.enQueue(4); // 返回 true circularQueue.Rear(); // 返回 4
# 代码
typedef struct {
int* a;
int front;
int rear;
int k;
} MyCircularQueue;
bool myCircularQueueIsEmpty(MyCircularQueue* obj);//定义
bool myCircularQueueIsFull(MyCircularQueue* obj) ;
MyCircularQueue* myCircularQueueCreate(int k) {
MyCircularQueue*obj=(MyCircularQueue*)malloc(sizeof(MyCircularQueue));
obj->a=(int*)malloc(sizeof(int)*(k+1));
obj->front=obj->rear=0;
obj->k=k;
return obj;
}
bool myCircularQueueEnQueue(MyCircularQueue* obj, int value) {
if( myCircularQueueIsFull(obj))//入队 如果满了就不用入队了
{
return false;
}
obj->a[obj->rear++]=value;
obj->rear%=(obj->k+1);//有可能处于最后一个位置 若想要返回第一个位置%k+1
return true;
}
bool myCircularQueueDeQueue(MyCircularQueue* obj) {
if(myCircularQueueIsEmpty(obj))//出队 若没有数据出队 就返回false
{
return false;
}
obj->front++; //数组中 front++ 就代表消除
obj->front%=(obj->k+1); //有可能处于最后一个位置 若想要返回第一个位置%k+1
return true;
}
int myCircularQueueFront(MyCircularQueue* obj) {
if(myCircularQueueIsEmpty(obj))
{
return -1;
}
return obj->a[obj->front];
}
int myCircularQueueRear(MyCircularQueue* obj) {
if(myCircularQueueIsEmpty(obj))
{
return -1;
}
int rear=obj->rear==0?obj->k:obj->rear-1;//若rear为下标为0的位置处,就要返回到-1处 会报错
return obj->a[rear]; //实际上是返回到 下标为k的位置处
}
bool myCircularQueueIsEmpty(MyCircularQueue* obj) {
return obj->front==obj->rear;
}
bool myCircularQueueIsFull(MyCircularQueue* obj) {
return (obj->rear+1)%(obj->k+1)==obj->front;//多开辟了一块空间 就是为了当入了k个数据后
//rear++ 处于 第k+1个位置处 ,%k+1正好为 下返回到标为0的位置处
}
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);
*/
解析
1.队列为空时
当为空时 rear==front
2.队列满的情况
-
判断满的情况
- 当k=4,k+1=5时,rear++
- 因为循环队列,所以应返回到 下标为0处
- rear==4, (rear+1)%(k+1)=5%5=0
3.入队列
- 正常来说 入一个数据后,rear++,但当处于以下位置时就需要考虑到循环返回到下标为0位置的情况
- 此时 的 rear++ ,rear=5 ,rear%(k+1)=5%5=0
4. 出队列
出队列时,每次front++,但当处于以下位置时需要考虑到循环返回到下标为0位置的情况
此时 的 front++ ,front=5 ,front%(k+1)=5%5=0
5.出队尾数据
因为每次 rear入一个数据后,都会++,所以需要找 obj->a[obj->rear-1] 但是需要考虑到以下位置
- 当rear处于下标为0的位置,rear-1为下标为-1的位置就会报错
- rear这里的位置是 在4的位置后 ,rear++后,%k+1得来的,而4的位置正好为k所在所以判断下
- int rear= rear==0?k:rear-1;