设计一个循环队列(c++)

目录

  • 接口及要求
  • 开始错误的逻辑
  • 修改思路
  • 代码

接口及要求

题目链接
设计一个循环队列(c++)_第1张图片

开始错误的逻辑

看到队列,首先我就想到了用链表来实现,但是这道题实际上用数组实现比较好一点,题目中提到循环,说明他是定长的一个队列,且要重复利用队列之前的空间存储新值。

设计一个循环队列(c++)_第2张图片

rear++,始终要指向当前元素的下一个用于插入数据
设计一个循环队列(c++)_第3张图片
与前面对比,当队列数据满了front 和rear也是相等的,那么到底是队列为空front与rear相等,还是队列满元素两者相等?这只是两个例子,还有很多的测试用例可以证明,因为无法区分两种情况,说明这样的循环队列结构已经出现问题.

修改思路

所以我们让队列多开一个空间,让这个位置永远空出来(并不需要一直是最后一个位置空)用于判断队列满和空。
设计一个循环队列(c++)_第4张图片
当rear+1等于front时,队列满。怎 么实现呢?
假设现在数组大小是k,只需要rear的下标%k,就能得到自己的下标,队列要满front永远在rear的前一个所以(rear+1)%k就能得到front的值,人家题目给的数组大小是k,我们要多开一个空间,所以数组大小为k+1,所以front下标的位置就是(rear+1)%(k+1),所以判断条件就是(rear+1)%(k+1)==front`
设计一个循环队列(c++)_第5张图片
空的位置是任意的,与场景有关:
设计一个循环队列(c++)_第6张图片

当front等于rear时队列为空(front++,删除数据)
设计一个循环队列(c++)_第7张图片

代码

然后开始写代码即可,但是要注意各种边界问题,尤其是头和尾

typedef struct {
     
   int* _a;
   int  _front;
   int  _rear;
   int  _k;
} MyCircularQueue;


MyCircularQueue* myCircularQueueCreate(int k) {
     
    //假如这里 MyCircularQueue* q;然后初始化q,返回q是错误的。因为出函数q所指向的地址被free掉,外面接收了q,还在指人家的地址,悬空指针
    //必须malloc
    MyCircularQueue* q=(MyCircularQueue*)malloc(sizeof(MyCircularQueue));
    //多开一个
    q->_a=(int*)malloc(sizeof(int)*(k+1));
    q->_front=0;
    q->_rear=0;
    q->_k=k;
    return q;

}
bool myCircularQueueIsEmpty(MyCircularQueue* obj);
bool myCircularQueueIsFull(MyCircularQueue* obj);

bool myCircularQueueEnQueue(MyCircularQueue* obj, int value) {
     
    //满了就不插
    if(myCircularQueueIsFull(obj))
    {
     
        return false;
    }
    obj->_a[obj->_rear]=value;
    //假设数组4个元素,大小为4+1,到了数组末尾下标为4,
    obj->_rear++;
    //不越界:就是自身的位置,越界:数组一越界就把他放到数组头(4++后5,5%5=0,)
    obj->_rear%=obj->_k+1;
    return true;

}

bool myCircularQueueDeQueue(MyCircularQueue* obj) {
     
  //空就不删
  if(myCircularQueueIsEmpty(obj))
  {
     
      return false;
  }
  
  
      obj->_front++;
      //和插入的时候%k+是一样的意思
      obj->_front%=obj->_k+1;
      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;
    }
    else
    {
     
     int tail=obj->_rear-1;
     //当rear为0时减1变成-1,这种情况我们单独做个判断
     if(tail==-1)
     {
     
         tail=obj->_k;
     }
     return obj->_a[tail];
    }

}

bool myCircularQueueIsEmpty(MyCircularQueue* obj) {
     
     return obj->_front==obj->_rear;
}

bool myCircularQueueIsFull(MyCircularQueue* obj) {
     
     return (obj->_rear+1) % (obj->_k+1)==obj->_front;
}

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);
*/

你可能感兴趣的:(Online,Judge,数据结构,队列,数据结构)