数据结构—循环队列

数据结构---循环队列

循环队列

一般在操作系统课程讲解生产者消费者模型时可以就会使用循环队列。环形队列可以使用数组实现,也可以使用循环链表实现。

为了能使下标Qrear = Qfront来区别队空还是队满,我们常常认为以下左图为队空,右图为队满的情况。a1到a7为7个有效数据,有效数据k个;左图初始空队列状态,我们认为Qrear=Qfront=0,右图此时满队列的状态,Qrear=7,Qfront=0

设计循环队列

结构体的创建

c 复制代码
typedef struct {
    int*a;//用动态数组实现
    int front;//头的下标
    int rear;//尾的下标
    //所以front和rear的取值都是0~k
    int k;//队列长度,有效数据长度为k
} MyCircularQueue;

循环队列的初始化

c 复制代码
MyCircularQueue* myCircularQueueCreate(int k) {
    MyCircularQueue* obj = (MyCircularQueue*)malloc(sizeof(MyCircularQueue));
    if(NULL == obj)//动态开辟结构体指针(销毁空间时也需free)
    {
        perror("malloc obj faile\n");
        return NULL;
    }
    obj->front = obj ->rear = 0;//初始队列元素为空,头尾在一起下标都为0
    obj->a = (int*)malloc(sizeof(int)*(k+1));//动态数组开辟k+1个空间,因为实际队列长度要比有效数据长度多一个空间
    if(obj->a == NULL)
    {
        perror("malloc obj->a faile");
        return NULL;
    }
    obj->k= k;//队列有效数据长度
    return obj;
}

判空

因为这是循环队列,在经过不断的插入删除的过程中,rear和front会不断地变换位置,所以判空条件就是判断他俩是否相等而不是他俩是否都为0

c 复制代码
bool myCircularQueueIsEmpty(MyCircularQueue* obj) {
    return obj->front == obj->rear;//若rear和front相等即为空
}

判满

判满条件只需要看(rear+1)%(k+1)==front就好了

c 复制代码
//判满
bool myCircularQueueIsFull(MyCircularQueue* obj) {
    return (obj->rear+1) % (obj->k+1) == obj->front;
}

插入(尾插)

c 复制代码
boolmyCircularQueueEnQueue(MyCircularQueue* obj, int value) {
    //有插入就要判断空间问题,判断队列是否满了
    if(myCircularQueueIsFull(obj))
    {
        return false;//插入失败返回false
    }
    obj->a[obj->rear++] = value;
    obj->rear %= obj->k+1;//rear为下标取值范围为0~k,所以这里限制以下rear的取值范围
    return true;
}

出队列(头删)

删除要判断是否为空队列,空队列不可以删除;头删原理就是,自增front,同样在进行头删的时候,因为front的自增,在动态数组a[k]到a[0]之间的过渡也需要对front取值范围的限制。

c 复制代码
bool myCircularQueueDeQueue(MyCircularQueue* obj) {
    //删除就要判空
    if(myCircularQueueIsEmpty(obj))
    {
        return false;
    }
    ++obj->front;
    obj->front %= obj->k+1;
    return true;
}

取队头元素

c 复制代码
int myCircularQueueFront(MyCircularQueue* obj) {
    if(myCircularQueueIsEmpty(obj))
    {
        return -1;//队列为空返回-1
    }
    return obj->a[obj->front];
}

取队尾元素

c 复制代码
int myCircularQueueRear(MyCircularQueue* obj) {
    if(myCircularQueueIsEmpty(obj))
    {
        return -1;//队列为空返回-1
    }
    return obj->a[(obj->rear-1+obj->k+1) % (obj->k+1)];
}

空间的销毁

c 复制代码
//空间的销毁
void myCircularQueueFree(MyCircularQueue* obj) {
    free(obj->a);
    obj->a = NULL;//防止野指针形成
    free(obj);
    obj = NULL;
}
相关推荐
Nobkins27 分钟前
2021ICPC四川省赛个人补题ABDHKLM
开发语言·数据结构·c++·算法·图论
易只轻松熊3 小时前
C++(23):容器类<vector>
开发语言·数据结构·c++
小学生的信奥之路3 小时前
力扣1991:找到数组的中间位置(前缀和)
数据结构·算法·leetcode·前缀和·数组
এ᭄画画的北北3 小时前
力扣-102.二叉树的层序遍历
数据结构·算法·leetcode
ccLianLian3 小时前
数据结构·字典树
数据结构·算法
Lu Yao_3 小时前
用golang实现二叉搜索树(BST)
开发语言·数据结构·golang
JeffersonZU5 小时前
【数据结构】2-3-1单链表的定义
数据结构·链表
JeffersonZU5 小时前
【数据结构】1-4算法的空间复杂度
c语言·数据结构·算法
L_cl5 小时前
【Python 算法零基础 4.排序 ① 选择排序】
数据结构·算法·排序算法
无聊的小坏坏6 小时前
【数据结构】二叉搜索树
数据结构