【数据结构】设计循环队列

简介: 【数据结构】设计循环队列

🌍 设计循环队列 【难度:中等】


🏷️力扣地址:🌈622. 设计循环队列


🌍题目描述:

0a2653c851af460fa595bd959398a8f1.png

💥特别注意:


2d65d23f6d4748949b924e4057485923.png


无论是数组实现还是链表实现,都要多开一个空间,否则无法区分判空判满。即要存k个数据的循环队列,要开(k+1)个空间。

用数组实现,要注意当到了尾节点,如何将指针重置的问题

考虑到,用指针实现,不仅仅要找尾,还要找尾的上一个,都挺麻烦的,所以接下来我要用数组实现一下


🌠动图解析:👇🏻

92ba0822ed0b46e1ae72df8a17d3a45b.png


🎄 入对列


💫关键思路:


【极端思维】如果队列已经满了,还要继续插入吗? ❌应该直接返回false

入队列,tail++,然后插入数据

【极端思维】当tail去到k+1 的时候,tail就要回到k==0的位置

🌠动图解析:👇🏻


92ba0822ed0b46e1ae72df8a17d3a45b.png


代码实现💡:


bool myCircularQueueEnQueue(MyCircularQueue* obj, int value) {
    if(myCircularQueueIsFull(obj))
        return false;
    obj->a[obj->tail] = value;
    obj->tail++;
    if(obj->tail == k+1)
       obj->tail =0;
    //取模法 ~ 画图理解
    //obj->tail = (k+1);
    return true;
}


🎄判断队列是否满


💫关键思路:


定义一个next作为tail的下一个节点


【极端思维】当next去到k+1 的时候,next就要回到k==0的位置


🌠动图解析:👇🏻


0a2653c851af460fa595bd959398a8f1.png


代码实现💡:


bool myCircularQueueIsFull(MyCircularQueue* obj) {
    int next = obj->tail + 1;
    if(next == k+1)
       next = 0;
    return next == obj->head;
}


🎄判断队列是否为空


💫关键思路:


出队列一个,head++,直到head == tail的时候,队列为空

这里比较简单直接上代码

代码实现💡:


bool myCircularQueueIsEmpty(MyCircularQueue* obj) {
    return obj->head == obj->tail;
}


🎄出队列


💫关键思路:


【极端思维】:还是和上面的一样:当head走到k+1的时候,要重置一下head,回到k=0

代码实现💡:


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


🎄取出队尾数据


💫关键思路:


【极端思维】:当tail在k=0的时候,队尾的数据应该在tail=k的位置,也就是下图中的5的位置

取模法:每次++,下一次都可能越界,就%= k+1处理一下

🌠画图解析:👇🏻


0a2653c851af460fa595bd959398a8f1.png


代码实现💡:


int myCircularQueueRear(MyCircularQueue* obj) {
    if(myCircularQueueIsEmpty(obj))
      return -1;
    int prev = obj->tail-1;
    if(obj->tail ==0)
      prev =obj->k;
    //取模法
    //int prev = obj -> tail-1 + k + 1;
    // prev %= (k+1);
    return true;
}


🎄销毁队列


💫特殊注意:


我们可以直接把obj给free掉吗? ❌

结构如下



如果我先把obj给释放掉,那么开创的数组空间就是内存泄漏了

所以应该先释放数组空间,再释放结构体空间

代码实现💡:


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


意外发生:


0a2653c851af460fa595bd959398a8f1.png


遇到这样的报错,其实是因为前面的函数调用了后面的函数接口,那在前面声明一下就好了,也可以把顺序换一下就行


完整代码如下:


typedef struct {
    int *a;
    int k;
    int tail;
    int head;
} MyCircularQueue;
MyCircularQueue* myCircularQueueCreate(int k) {
    MyCircularQueue* obj = (MyCircularQueue*)malloc(sizeof(MyCircularQueue));
    obj->a = malloc(sizeof(int)*(k+1));//因为要多开一个空间去判断 空or满
    obj->head = obj->tail =0;
    obj->k = k;
    return obj;
}
bool myCircularQueueIsEmpty(MyCircularQueue* obj) {
    return obj->head == obj->tail;
}
bool myCircularQueueIsFull(MyCircularQueue* obj) {
    int next = obj->tail + 1;
    if(next == obj->k+1)
       next = 0;
    return next == obj->head;
}
bool myCircularQueueEnQueue(MyCircularQueue* obj, int value) {
    if(myCircularQueueIsFull(obj))
        return false;
    obj->a[obj->tail] = value;
    obj->tail++;
    if(obj->tail == obj->k+1)
       obj->tail =0;
    return true;
}
bool myCircularQueueDeQueue(MyCircularQueue* obj) {
    if(myCircularQueueIsEmpty(obj))
      return false;
    ++obj->head;
    if(obj->head == obj->k+1)
       obj->head =0;
    return true;
}
int myCircularQueueFront(MyCircularQueue* obj) {
    if(myCircularQueueIsEmpty(obj))
      return -1;
    return obj->a[obj->head]; 
}
int myCircularQueueRear(MyCircularQueue* obj) {
    if(myCircularQueueIsEmpty(obj))
      return -1;
    int prev = obj->tail-1;
    if(obj->tail ==0)
      prev =obj->k;
    return obj->a[prev];
}
void myCircularQueueFree(MyCircularQueue* obj) {
     free(obj->a);
     free(obj);
}


可能我们还是对取模法有点不清晰,接下来看这道题目


现有一循环队列,其队头指针为front,队尾指针为rear;循环队列长度为N。其队内有效长度为?(假设队头不存放数据)

A (rear - front + N) % N + 1

B (rear - front + N) % N

C ear - front) % (N + 1)

D (rear - front + N) % (N - 1)

解析如图:


0a2653c851af460fa595bd959398a8f1.png


答案:B


总结:


取模的时候,要注意有需要的时候可以加上队列的长度,然后再模


📢写在最后


能看到这里的都是棒棒哒🙌!

想必栈和队列也算是数据结构中比较难🔥的部分了,如果认真看完以上部分,肯定有所收获。

接下来我还会继续写关于📚《排序》等…

💯如有错误可以尽管指出💯

🥇想学吗?我教你啊🥇

🎉🎉觉得博主写的还不错的可以一键三连撒🎉🎉


相关文章
|
6天前
|
存储 Java 容器
深入浅出 栈和队列(附加循环队列、双端队列)
深入浅出 栈和队列(附加循环队列、双端队列)
|
19天前
|
存储
【数据结构】循环队列
【数据结构】循环队列
26 0
|
19天前
|
算法 调度 C++
【C/C++ 数据结构 线性表】C/C++中队列的原理与实现:从基础到循环队列
【C/C++ 数据结构 线性表】C/C++中队列的原理与实现:从基础到循环队列
48 0
数据结构第九弹---循环队列
数据结构第九弹---循环队列
|
8月前
|
算法 C语言
【数据结构】循环队列
文章目录 📑前言 🍁一、循环队列的结构 💭 二、循环队列的操作 1.定义循环队列 2.创建循环队列 3.判断满
|
7月前
|
存储 算法 编译器
【霍洛维兹数据结构】栈和队列 | 动态循环队列 | 迷宫问题 | 表达式 | 多重栈&多重队列
【霍洛维兹数据结构】栈和队列 | 动态循环队列 | 迷宫问题 | 表达式 | 多重栈&多重队列
54 0
|
19天前
|
C++
数据结构(顺序队列 循环队列
数据结构(顺序队列 循环队列
12 0
|
19天前
数据结构——循环队列的实现(下)
数据结构——循环队列的实现(下)
|
19天前
|
存储 C语言
数据结构——循环队列的实现(上)
数据结构——循环队列的实现
|
19天前
|
C语言
C语言数据结构(队列、循环队列)
C语言数据结构(队列、循环队列)
13 0