瞬解 队列 -- 循环队列问题(超超超详解)

简介: 瞬解 队列 -- 循环队列问题(超超超详解)

什么是循环队列:

在我们写那到题之前 我们得先了解循环队列是什么样的结构:>

b60481d432994e2b9eb6833dd3c5fc21.gif

 就是这样 空间填满了之后回到开始得位置 可以之前的数据删掉 来存储新的数据  这样我们就可以使用这种结构 用一定的存储空间 来存储更多的数据 那了解完 来看看我们的题吧


:力扣

这里其实用 数组 和 链表 的区别不大其实

但是都是要用到两个变量来记录这个队列的对头和队尾的也就是 front 和 back

那既然这样 我们在 增加,删除数据的时候front 和 back 怎么变化内


其实很简单 在我们增加数据的时候back++就可以了 删除数据的时候 front++就可以了

而当back已经填完了数组要回到下标为0的位置  而链表只要把把front置为front->next 所以要用链表的话 设置成循环链表会更好  实际上也差不了多少 这里我们就用数组来解决了


我们之前不是设置了front 和 back 嘛  而且我们填满了之后不是要删一些数据才能继续嘛 所以什么时候为满 什么时候为空内? 这是个问题大家可以思考一下下

217e261368514682ad4d2b63b3eca27c.png大家看就遇到这种情况了 那该怎么解决这个问题内? 


5e65f4c0d3ad4f91847dae00c276bd1c.png


 我们更正好思路后 在来看这道题:>

b67ed321d24d486297d9b425a579b118.png因为我们设定的这个循环队列里面是有几个变量 就把他们全部包在一起

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

 因为这个循环队列 里面放的整型数据所以是int*类型  加之我们这里使用数组的方法来实现的,大家也可以下可以下来是一下链表的方式来实现

这里的 k 也就是我们这个空间能够放的数据的最大数量  放在里面是因为 题目给我们的 k 只在后面的  MyCircularQueue* myCircularQueueCreate(int k) 里面给出 加上我们后面有判断临界时会用到 所以也要包在里面

31f1fac6700c4e0dbd211d27e777c0a6.png

 因为如果我们只是单一的创建一个变量 再对变量里面的成员赋值 最后返回我们创建的变量的地址 大家想想这样可以嘛?


首先 我们想想一个函数在返回后 这里面给变量分配的空间会怎么样?

怎么样是不是已经有答案了呢

也就是说  在我们决定一个函数的返回值的时候 尽量不要返回函数中临时变量的地址 我本人是不建议在编写一个函数的时候这样做的  因为你返回后你这个函数的临时变量的空间就被还回去了 而这个指向这片空间的地址(指针)还指向这里的 所以如果你在使用这种指针 也就是 用了 野指针 了 这样肯定是不行的  所以平常我们在对于指针的控制 要变得敏感一点

像不用的指针 就把它置为空  就好像 一条狗 你不希望它去做任何事情只想让它留在原地 就拿绳子栓着 或者 让别人看着  这里的限制条件就是 NULL  

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

41e4fb60f68c438f9ebc7115812bdefe.png

这里面的printf不属于 这个函数的实现 这个在我在调试的时候使用的一个小方法 因为对于这种多接口型的这种题 又时我们不知到 是哪里突然结束 的时候就可以这样

这个函数是用来填数据 我们肯定是先填数据再把tail往后面移动  所以先把数据填进去 在来看back该怎么移动是不是到达临界  如果是链表可以省去判断这一步骤

在填入数据之前还得看一下这个空间是不是有余的所以要判断一下 空间是否满 如果是满的就直接返回 false

ce7133387b824278851ba235c8009467.png


这个删除数据的函数和填入数据 相差不大 删除数据就只需要 把front往前移就可以了 之前的数据你可以把 它置为其他数据 也可以不用管它

5c13e8ba5df749598b5378f545b91473.png这个是返回头和尾的函数对于返回头 就只需要返回front所在的位置就可以了 因为front一直都是头

返回尾的函数 就像上面 说的back是在最后一个数据的下一个位置 所以在返回尾的时候 只需要

返回back-1位就可以了 但back是有可能为0的 所以要进行判断 不然会造成数组越界 当back为0时 那它的前一个在哪里呢? 是不是在整个空间的 末尾 所以这个返回k位就可以了

(k为3 我们开辟4个空间 最后一个空间下标正好为3)

8460a5056c524974a135579c234a5c17.png

这个是判空 判满函数 判空很容易就只需要 判断front==back 就行了

判满函数 当你填入数据为满时有两种情况

ffa7732e973643fcaded6a8c0157a50a.png

就是这样如果不是在空间的头尾 那么就来看back+1==front就行了

注意 在使用 判空 判满函数时要注意 他们放的位置因为 程序在使用一个函数是向上查找 如果放在下面 它会报错

e6cc56c0f1e34e438f596fac370b6999.png最后的这个free函数就没什么好说的了 就把我们之前开辟的空间free掉就可以了


这样我们循环队列就说完了 谢谢大家能够看到这里 祝大家以后都能拿到自己心仪大厂的offer!!

目录
相关文章
|
6月前
|
消息中间件 存储 搜索推荐
深入理解栈和队列(二):队列
深入理解栈和队列(二):队列
73 0
|
存储 C++
用队列实现栈VS用栈实现队列
用队列实现栈VS用栈实现队列
31 0
|
6月前
|
存储 算法 Java
【数据结构与算法】7、队列(Queue)的实现【用栈实现队列】
【数据结构与算法】7、队列(Queue)的实现【用栈实现队列】
74 0
|
6月前
|
缓存
队列的实现及操作(链表实现)
队列的实现及操作(链表实现)
|
6月前
|
存储 缓存 算法
队列的学习(二) 循环队列
队列的学习(二) 循环队列 循环队列是一种基于数组实现的队列,相比于普通队列,它的插入和删除操作更加高效。循环队列可以避免在队列头部删除元素时进行大量的数据搬移操作,实现了队列的“循环利用”。
|
C++
7.5 C/C++ 实现链表队列
链表队列是一种基于链表实现的队列,相比于顺序队列而言,链表队列不需要预先申请固定大小的内存空间,可以根据需要动态申请和释放内存。在链表队列中,每个节点包含一个数据元素和一个指向下一个节点的指针,头节点表示队头,尾节点表示队尾,入队操作在队尾插入元素,出队操作在队头删除元素,队列的长度由节点数量决定。由于链表队列没有容量限制,因此可以处理任意数量的元素,但是相比于顺序队列,链表队列的访问速度较慢,因为需要通过指针来访问下一个节点。
74 0
|
人工智能
FIFO队列和优先队列
FIFO队列和优先队列
100 0
|
C语言
【Leetcode】队列实现栈和栈实现队列
【Leetcode】队列实现栈和栈实现队列
65 0
|
算法
LeetCode每日1题--用队列实现栈
LeetCode每日1题--用队列实现栈
65 0