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

接口及要求

题目链接
在这里插入图片描述

开始错误的逻辑

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

在这里插入图片描述

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

修改思路

所以我们让队列多开一个空间,让这个位置永远空出来(并不需要一直是最后一个位置空)用于判断队列满和空。
在这里插入图片描述
当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`
在这里插入图片描述
空的位置是任意的,与场景有关:
在这里插入图片描述

当front等于rear时队列为空(front++,删除数据)
在这里插入图片描述

代码

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

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);
*/
  • 4
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

楠c

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值