leetcode622. 设计循环队列

时间:2022-11-14 12:18:56

题目

设计你的循环队列实现。 循环队列是一种线性数据结构,其操作表现基于 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 leetcode622. 设计循环队列

2.队列满的情况

  • 判断满的情况

  • 当k=4,k+1=5时,rear++
  • leetcode622. 设计循环队列
  • 因为循环队列,所以应返回到 下标为0处
  • rear==4, (rear+1)%(k+1)=5%5=0

3.入队列

  • 正常来说 入一个数据后,rear++,但当处于以下位置时就需要考虑到循环返回到下标为0位置的情况
  • leetcode622. 设计循环队列
  • 此时 的 rear++ ,rear=5 ,rear%(k+1)=5%5=0

4. 出队列

出队列时,每次front++,但当处于以下位置时需要考虑到循环返回到下标为0位置的情况

leetcode622. 设计循环队列

此时 的 front++ ,front=5 ,front%(k+1)=5%5=0

5.出队尾数据

因为每次 rear入一个数据后,都会++,所以需要找 obj->a[obj->rear-1] 但是需要考虑到以下位置 leetcode622. 设计循环队列

  • 当rear处于下标为0的位置,rear-1为下标为-1的位置就会报错
  • rear这里的位置是 在4的位置后 ,rear++后,%k+1得来的,而4的位置正好为k所在所以判断下
  • int rear= rear==0?k:rear-1;