队列OJ--循环队列

目录

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

题解:

​编辑

代码实现:

完整代码:


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


题解:

        循环队列的意思就是,如果将插入的数据删除后,原来的空间可以重复使用。

        我们能想到的就是利用数组或者链表这两种数据结构。

        如果使用数组的话那么数组到尾之后,要将下标置为0。

        如果使用链表的话,那么可能就要用到双向链表,当到达尾部的时候,就要重新回到头。但每次插入新的数据的时候,都要malloc新的节点,无疑增大了工作量,似乎会更复杂一些。

        本题我们就使用数组来实现:数组到尾之后,要将下标置为0,然后开始新一轮的循环。

        这时我们就遇到两个问题了,什么时候为空?什么时候为满?

        为空的情况我们是很容易想到的,此时我们定义两个指针,front(控制出队)和back(控制入队),如果front等于back那我们就认为数据为空。

        那空我们解决了,那什么情况又为满呢?

        当back到达尾部时,下标重置,此时front==back,此时可以为满?这样的话,back==front既是空,又是满,这样两种情况就区分不开了。

        这里有两种方法:1.增加一个size,size==0为空,非为插入数据总数就是满。

                                     2.增加一个控制位。

        这里我们就选择第二种方法来实现,增加一个控制位。这个位置也是存放数据的,循环起来空的是任意位置,如果插入4个数据,我们就开5个数据大小的空间。

        我们让back永远指向数据的下一个位置,back位置就不存数据。

        这样一来,如果back的下一个是front,那就代表数据存满了。

        随之也会出现下面两种情况,右边的这种情况real+1==front就能判断存满了。那左边这个back+1他就不能判断了,还会造成假越界的问题。这时我们就可以让back+1模上一个k

+1,表达式就可以写成:(back+1)%(k+1)==front。左边back值为4,这时(4+1)%(4+1)==0成立。右边(1+1)%(4+1)==2成立。这样一来问题就解决了。


代码实现:

1.结构体成员介绍:

typedef struct {
    int*a ;
    int front;
    int back;
    int k;
} MyCircularQueue;

        a为开辟的数组,k为入队数据个数  。

2.初始化

MyCircularQueue* myCircularQueueCreate(int k) {
    MyCircularQueue*obj = (MyCircularQueue*)malloc(sizeof(MyCircularQueue));
    obj->a = (int*)malloc(sizeof(int)*(k+1));
    obj->front = 0;
    obj->back = 0;
    obj->k = k;
    return obj;
}

3.判空和判满

bool myCircularQueueIsEmpty(MyCircularQueue* obj) {
    return obj->front == obj->back;
}

bool myCircularQueueIsFull(MyCircularQueue* obj) {
    return (obj->back+1)%(obj->k+1) == obj->front;
}

        实现下面接口要用到这两个函数,我们可以将之挪到前面,也可以在上面单独声明。

4.入队

bool myCircularQueueEnQueue(MyCircularQueue* obj, int value) {
    if(myCircularQueueIsFull(obj))
        return false;
    obj->a[obj->back]=value;
    ++obj->back;
    (obj->back) %=(obj->k+1);
    return true;
}

        入队需要注意:首先要判满,然后插入数据,最后还要考虑如果back下标如果到尾,还要将back重置为0,这里我们也可以用到取模的方法,back小于k+1back值不变back=k+1 back=k+1,back重置为0。

5.出队

bool myCircularQueueDeQueue(MyCircularQueue* obj) {
    if(myCircularQueueIsEmpty(obj))
        return false;
    ++obj->front;
    obj->front %=(obj->k+1);
    return true;
}

        出队需要注意:首先要判空,然后删除数据,和back一样也要检出front下标是否到尾。

6.取队头数据

int myCircularQueueFront(MyCircularQueue* obj) {
    if(myCircularQueueIsEmpty(obj))
        return -1;
    return obj->a[obj->front];
}

        取队头数据,先要判空,如果为空,根据题目要求要返回-1,否则返回队头数据。

7.取队尾数据

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

         取队尾数据  ,先要判空,如果为空,根据题目要求要返回-1,否则返回队尾数据。

        如果遇到这种情况:back-1=-1,这就取不到队尾数据了。这时(obj->back-1+obj->k+1)%(obj->k+1)我们可以这样写,加上一个(k+1),就可以解决back为0 的情况了。如果back不为0,那么模上一个(k+1)就能把加上的(k+1)模掉。

8.free

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

完整代码:

typedef struct {
    int*a ;
    int front;
    int back;
    int k;
} MyCircularQueue;


MyCircularQueue* myCircularQueueCreate(int k) {
    MyCircularQueue*obj = (MyCircularQueue*)malloc(sizeof(MyCircularQueue));
    obj->a = (int*)malloc(sizeof(int)*(k+1));
    obj->front = 0;
    obj->back = 0;
    obj->k = k;
    return obj;
}
bool myCircularQueueIsEmpty(MyCircularQueue* obj) {
    return obj->front == obj->back;
}

bool myCircularQueueIsFull(MyCircularQueue* obj) {
    return (obj->back+1)%(obj->k+1) == obj->front;
}
bool myCircularQueueEnQueue(MyCircularQueue* obj, int value) {
    if(myCircularQueueIsFull(obj))
        return false;
    obj->a[obj->back]=value;
    ++obj->back;
    (obj->back) %=(obj->k+1);
    return true;
}

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

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

  • 25
    点赞
  • 16
    收藏
    觉得还不错? 一键收藏
  • 19
    评论
SDUT-OJ(Software Development University of Tsinghua Online Judge)是一个在线编程平台,提供给清华大学软件学院的学生和爱好者练习和解决算法问题的环境,其中包括各种计算机科学题目,包括数据结构、算法、图形等。对于"最小生成树"(Minimum Spanning Tree, MST)问题,它是图论中的经典问题,目标是从一个加权无向图中找到一棵包含所有顶点的树,使得树的所有边的权重之和最小。 在C语言中,最常见的是使用Prim算法或Kruskal算法来求解最小生成树。Prim算法从一个顶点开始,逐步添加与当前生成树相连且权重最小的边,直到所有顶点都被包含;而Kruskal算法则是从小到大对所有边排序,每次选取没有形成环的新边加入到树中。 如果你想了解如何用C语言实现这些算法,这里简单概括一下: - 通常使用优先队列(堆)来存储边和它们的权重,以便快速查找最小值。 - 从任意一个顶点开始,遍历与其相邻的边,若新边不形成环,就更新树,并将新边加入优先队列。 - Kruskal算法: - 先将所有的边按照权重升序排序。 - 创建一个空的最小生成树,然后依次取出排序后的边,如果这条边连接的两个顶点不在同一个连通分量,则将其添加到树中。 如果你需要更详细的代码示例,或者有具体的问题想了解(比如如何处理环、如何实现优先队列等),请告诉我,我会为你提供相应的帮助。
评论 19
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值