设计循环队列

一.题目描述

在这里插入图片描述

二.题目分析

在这里插入图片描述

图中一共有八块空间,是否可以全部用来存储数据呢?

若数据为空,如图所示,front==rear;
若数据满了,如下图所示,front同样和rear一样,指向同一块空间

在这里插入图片描述

如何区分呢??
第一种方法:假设一共有k+1个空间,其中k个空间用来存储数据,剩下一个空置,不用来存储,以便区分,队列满时:rear+1=front
第二方法:设置一个size记录元素个数,size==k+1时空间满了,size==0时为空。

这里我们采用第一种方法。

三.顺序表链表的选择

链表

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

分析: 数据为空时:rear和front指向同一块空间。
    数据满时:rear->next==front.

在这里插入图片描述

观察题目要求,发现最难搞得就是获取队尾元素
1.采用双向链表
2.增加一个指针,指向rear的前一个
3.遍历一遍找到对位数据

顺序表

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

在这时候,7还没有插入,但是rear下标越界了,这是一个循环队列,要达到循环的效果,移动rear,如图所示。

在这里插入图片描述

(rear+1)%(k+1)

在这里插入图片描述

通过观察,两个下标之间相差6,也就是队列元素个数
rear+1=(rear+1)%(k+1)

正常情况下:队列满了,rear+1=front就满了,但是这个rear+1是经过(rear+1)%(k+1)转化过来
所以队列满:(rear+1)%(k+1)==front
队列空:rear==front

我们采用顺序表方式实现。

四.代码实现

//循环队列
typedef struct
{
    int*a;
    int k;
    int rear;
    int front;
} MyCircularQueue;

MyCircularQueue* myCircularQueueCreate(int k) 
{
     MyCircularQueue*obj=(MyCircularQueue*)malloc(sizeof(MyCircularQueue));
     //注意,这里的k个空间是用来存储元素的,以免产生分歧,创建k+1个
     obj->a=(int*)malloc(sizeof(int)*(k+1));
     obj->rear=obj->front=0;
     obj->k=k;
     return obj;
}
//题目中将以下两个函数接口放到了后面,但是在前面函数中要使用,
//函数要先声明后定义,放到前面就不用生命力,直接使用。
bool myCircularQueueIsEmpty(MyCircularQueue* obj) 
{
    return obj->rear==obj->front;
}
bool myCircularQueueIsFull(MyCircularQueue* obj) 
{
    
        return   (obj->rear+1)%(obj->k+1)==obj->front;
}

bool myCircularQueueEnQueue(MyCircularQueue* obj, int value) 
{
    if(myCircularQueueIsFull(obj))
    {
        return false;
    }
    obj->a[obj->rear]=value;
    obj->rear++;
    //rear走到最后的位置需要挪到前面去。
    obj->rear%=(obj->k+1);
    return true;
}

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

void myCircularQueueFree(MyCircularQueue* obj)
{
    free(obj->a);
    free(obj);
}

在这里分析一下这段代码

int myCircularQueueRear(MyCircularQueue* obj) 
{
     if(myCircularQueueIsEmpty(obj))
    {
        return -1;
    }
    
    return obj->a[(obj->rear+obj->k)%(obj->k+1)];
}

在这里插入图片描述

正常情况下取队尾数据就访问下标为rear-1的数据就可以。但是上面图是一个特例: rear-1就越界,而他的前一个为

在这里插入图片描述

rear在这个位置,所以需要加上数据元素(rear-1+k+1)%(k+1) 化简为(rear+k)%(k+1)


容如有错误欢迎各位大神批评指正🙏大家如果觉得有帮助的话点个赞支持一下博主喔✊✊后续还会继续更新其他的笔试题给到大家,如感兴趣可以多多关注一下博主🔚

  • 3
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 2
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

lim 鹏哥

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

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

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

打赏作者

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

抵扣说明:

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

余额充值