设计循环队列

题目:622. 设计循环队列 - 力扣(LeetCode)

1、确定使用链表还是数组 

一看到循环,大家应该很容易想到循环链表,但是循环链表在此题中没有很大优势,我们优先选择数组。原因如下:

判断何时为空何时为满的情况(假设k=4)

i.front==rear为空,rear指向尾节点的下一个节点位置

但是会发现,当插入第四个数时,rear会又回到和front一样的位置上,这样就很难判断何时未满和空的情况。此时可以定义一个size,当size==0时为空,size==k为满,但这样给我们写代码加了很多难度,不建议。

再说找尾,找头很好找,但是找尾需要知道rear的上一个节点,那这样循环链表要变为双向循环链表,很麻烦。

ii.front==rear为空,rear指向尾节点

这样的确很好找头和尾,但是在删除最后一个数据的情况要特殊处理,也很麻烦。

iii.front指向头结点,rear==NULL为空。

这样当插入第一个数时,rear指向尾节点。但在删除数据的时候,删除第一个,front指向下一个。到最后一个数据,需要对rear进行单独处理。

综上,我们使用数组进行处理。

2.建立数组框架

我们在建立数组的时候,多建立一个。就比如k=4,我们建立数组的长度为5。多开一个空间解决假溢出问题。

3.判断何时为空、何时为满

3.1为空

rear==front为空,rear指向尾节点的下一个节点。

3.2为满

3.2.1第一种情况

rear+1==front为满

3.2.2第二种情况

这种情况就不能用rear+1==front来判断了。可以这样:(rear+1)%(k+1)== front来判断就可以了。这个式子也适用于第一种情况。

4.获取首元素

这个很好获取,front指向的就是首元素。

5.获取尾元素

5.1第一种情况

rear指向尾节点下一个元素,那获取尾元素需要rear-1

5.2第二种情况

这种情况肯定不能直接rear-1,用(rear-1+k+1)可以处理。

但是第一种情况不适用,那我们再%(k+1)。即(rear-1+k+1)%(k+1)

6.加入数据和删除数据

6.1加入数据

加入第四个元素时,rear不能直接+1,需要(rear+1)%(k+1),加入数据。

6.2删除数据

删除数据,我们直接front往后移动就行。

这种情况想要删除数据,不能直接front+1,需要(front+1)%(k+1)

代码如下:

typedef struct {
    int *a;
    int front;
    int rear;
    int k;
} MyCircularQueue;//使用数组

MyCircularQueue* myCircularQueueCreate(int k) {
    MyCircularQueue* Queue=(MyCircularQueue*)malloc(sizeof(MyCircularQueue));//malloc一个MyCircularQueue结构体
    Queue->a=(int*)malloc(sizeof(int)*(k+1));//malloc一个数组
    Queue->front=Queue->rear=0;
    Queue->k=k;
    return Queue;
}
bool myCircularQueueIsEmpty(MyCircularQueue* obj) {

    return obj->front==obj->rear;
}

bool myCircularQueueIsFull(MyCircularQueue* obj) {
    if((obj->rear+1)%(obj->k+1)==obj->front)return true;
    return false;
}
bool myCircularQueueEnQueue(MyCircularQueue* obj, int value) {
    if(myCircularQueueIsFull(obj))return false;
     obj->a[obj->rear]=value;
     obj->rear++;
     obj->rear =(obj->rear)%(obj->k+1);//这两步也可以合成obj->rear = (obj->rear+1)%(obj->k+1)
 
     return true;
}

bool myCircularQueueDeQueue(MyCircularQueue* obj) {
    if(myCircularQueueIsEmpty(obj))return false;
         obj->front++;
     obj->front =(obj->front)%(obj->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;
    return obj->a[(obj->rear-1+obj->k+1)%(obj->k+1)];
}



void myCircularQueueFree(MyCircularQueue* obj) {
    free(obj->a);//释放的话先释放obj->a
    obj->a=NULL;
    free(obj);//再释放obj
    obj=NULL;

}

谢谢你看到这里哟!

over~

  • 18
    点赞
  • 21
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值