数据结构——循环队列(数组实现)

简介: 数据结构——循环队列(数组实现)

一、概念


普通队列若采用数组实现,随着出队入队操作的进行,队头队尾指针的移动,队头指针走到数组0号位置之后,因为队列只能在队尾插入,那么队头前面的空间就无法再次使用,导致假溢出问题。因此提出了循环队列,其思想是队头或队尾指针到达空间最后一个位置后,下一步移动又会重新返回到初始位置,图示如下:


image.png


循环队列为空:队头队尾指针都在初始位置。


image.png


满循环队列:为了能使用Q.rear=Q.front来区别是队空还是队满,我们常常认为上图情况时为队满,此时rear+1=front。


注:图示只是为了便于对循环队列的理解,真实的队列还是依靠数组或者链表实现的,内存不会发生弯曲形成头尾相连的情况,而是对指针的操作,实现超过最大位置时就自动返回到初始位置形成循环。


实现方法:每次对队头队尾指针进行改变时,都要对最大容量size进行%取余。若有减法操作,还需先加上最大容量size再对size进行取余,防止数组越界。


二、结构体定义


//循环队列
typedef int QDataType;
typedef struct {
    QDataType* array;
    int front;//队头
    int rear;//队尾
    int size;//容量
} MyCircularQueue;


三、接口实现


bool myCircularQueueIsEmpty(MyCircularQueue* obj);//判空,空返回true,非空返回false
bool myCircularQueueIsFull(MyCircularQueue* obj);//判满,满返回true,非满返回false
MyCircularQueue* myCircularQueueCreate(int k);//初始化队列
bool myCircularQueueEnQueue(MyCircularQueue* obj, int value);//入队
bool myCircularQueueDeQueue(MyCircularQueue* obj);//出队
int myCircularQueueFront(MyCircularQueue* obj);//获取队头元素
int myCircularQueueRear(MyCircularQueue* obj);//获取队尾元素
void myCircularQueueFree(MyCircularQueue* obj);//销毁


1.循环队列初始化


MyCircularQueue* myCircularQueueCreate(int k) {//初始化队列
    MyCircularQueue* obj = (MyCircularQueue*)malloc(sizeof(MyCircularQueue));
    if (obj == NULL) {
        return NULL;
    }
    obj->array = (QDataType*)malloc(sizeof(QDataType) * (k + 1));//申请k+1一个空间
    obj->front = 0;
    obj->rear = 0;
    obj->size = k + 1;
    return obj;
}


2.循环队列入队


bool myCircularQueueEnQueue(MyCircularQueue* obj, int value) {//入队
    if (myCircularQueueIsFull(obj)) {
        return false;
    }
    obj->array[obj->rear] = value;
    obj->rear = (obj->rear + 1) % obj->size;
    return true;
}


3.循环队列出队


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


4.获取队头元素


int myCircularQueueFront(MyCircularQueue* obj) {//获取队头元素
    if (myCircularQueueIsEmpty(obj)) {
        return -1;
    }
    return obj->array[obj->front];
}


5.获取队尾元素


int myCircularQueueRear(MyCircularQueue* obj) {//获取队尾元素
    if (myCircularQueueIsEmpty(obj)) {
        return -1;
    }
    return obj->array[(obj->rear - 1+obj->size) % obj->size];
}


6.循环队列判空


bool myCircularQueueIsEmpty(MyCircularQueue* obj) {//判空
    if (obj->front == obj->rear) {
        return true;
    }
    return false;
}


7.循环队列判满


bool myCircularQueueIsFull(MyCircularQueue* obj) {//判满
    if ((obj->rear + 1) % obj->size == obj->front) {
        return true;
    }
    return false;
}


8.循环队列销毁


void myCircularQueueFree(MyCircularQueue* obj) {//销毁
    free(obj->array);
    free(obj);
}


四、接口测试


1.测试函数


void Test_Queue() {
    MyCircularQueue* obj = myCircularQueueCreate(3);
    myCircularQueueEnQueue(obj, 1);
    myCircularQueueEnQueue(obj, 2);
    myCircularQueueEnQueue(obj, 3);
    myCircularQueueEnQueue(obj, 4);//队满
    printf("front=%d\n", myCircularQueueFront(obj));//获取队头1
    printf("rear=%d\n", myCircularQueueRear(obj));//获取队尾3
    myCircularQueueDeQueue(obj);//出队1
    printf("front=%d\n", myCircularQueueFront(obj));//获取队头2
    myCircularQueueFree(obj);//销毁
}


2.测试结果


3.png


五、完整代码


#include<stdio.h>
#include<malloc.h>
#include<stdbool.h>
//循环队列
typedef int QDataType;
typedef struct {
    QDataType* array;
    int front;//队头
    int rear;//队尾
    int size;//容量
} MyCircularQueue;
bool myCircularQueueIsEmpty(MyCircularQueue* obj);//判空,空返回true,非空返回false
bool myCircularQueueIsFull(MyCircularQueue* obj);//判满,满返回true,非满返回false
MyCircularQueue* myCircularQueueCreate(int k) {//初始化队列
    MyCircularQueue* obj = (MyCircularQueue*)malloc(sizeof(MyCircularQueue));
    if (obj == NULL) {
        return NULL;
    }
    obj->array = (QDataType*)malloc(sizeof(QDataType) * (k + 1));//申请k+1一个空间
    obj->front = 0;
    obj->rear = 0;
    obj->size = k + 1;
    return obj;
}
bool myCircularQueueEnQueue(MyCircularQueue* obj, int value) {//入队
    if (myCircularQueueIsFull(obj)) {
        return false;
    }
    obj->array[obj->rear] = value;
    obj->rear = (obj->rear + 1) % obj->size;
    return true;
}
bool myCircularQueueDeQueue(MyCircularQueue* obj) {//出队
    if (myCircularQueueIsEmpty(obj)) {
        return false;
    }
    obj->front = (obj->front + 1) % obj->size;
    return true;
}
int myCircularQueueFront(MyCircularQueue* obj) {//获取队头元素
    if (myCircularQueueIsEmpty(obj)) {
        return -1;
    }
    return obj->array[obj->front];
}
int myCircularQueueRear(MyCircularQueue* obj) {//获取队尾元素
    if (myCircularQueueIsEmpty(obj)) {
        return -1;
    }
    return obj->array[(obj->rear - 1+obj->size) % obj->size];
}
bool myCircularQueueIsEmpty(MyCircularQueue* obj) {//判空
    if (obj->front == obj->rear) {
        return true;
    }
    return false;
}
bool myCircularQueueIsFull(MyCircularQueue* obj) {//判满
    if ((obj->rear + 1) % obj->size == obj->front) {
        return true;
    }
    return false;
}
void myCircularQueueFree(MyCircularQueue* obj) {//销毁
    free(obj->array);
    free(obj);
}
void Test_Queue() {
    MyCircularQueue* obj = myCircularQueueCreate(3);
    myCircularQueueEnQueue(obj, 1);
    myCircularQueueEnQueue(obj, 2);
    myCircularQueueEnQueue(obj, 3);
    myCircularQueueEnQueue(obj, 4);//队满
    printf("front=%d\n", myCircularQueueFront(obj));//获取队头1
    printf("rear=%d\n", myCircularQueueRear(obj));//获取队尾3
    myCircularQueueDeQueue(obj);//出队1
    printf("front=%d\n", myCircularQueueFront(obj));//获取队头2
    myCircularQueueFree(obj);//销毁
}
int main() {
    Test_Queue();
    return 0;
}



相关文章
|
4月前
|
存储 Java 程序员
数据结构之 - 深入了解数组数据结构
数据结构之 - 深入了解数组数据结构
63 6
|
15天前
|
存储 人工智能 算法
C 408—《数据结构》算法题基础篇—数组(通俗易懂)
408考研——《数据结构》算法题基础篇之数组。(408算法题的入门)
58 23
|
4月前
|
存储 算法 搜索推荐
探索常见数据结构:数组、链表、栈、队列、树和图
探索常见数据结构:数组、链表、栈、队列、树和图
147 64
|
3月前
|
存储 缓存 算法
在C语言中,数据结构是构建高效程序的基石。本文探讨了数组、链表、栈、队列、树和图等常见数据结构的特点、应用及实现方式
在C语言中,数据结构是构建高效程序的基石。本文探讨了数组、链表、栈、队列、树和图等常见数据结构的特点、应用及实现方式,强调了合理选择数据结构的重要性,并通过案例分析展示了其在实际项目中的应用,旨在帮助读者提升编程能力。
99 5
|
3月前
|
存储 人工智能 算法
数据结构实验之C 语言的函数数组指针结构体知识
本实验旨在复习C语言中的函数、数组、指针、结构体与共用体等核心概念,并通过具体编程任务加深理解。任务包括输出100以内所有素数、逆序排列一维数组、查找二维数组中的鞍点、利用指针输出二维数组元素,以及使用结构体和共用体处理教师与学生信息。每个任务不仅强化了基本语法的应用,还涉及到了算法逻辑的设计与优化。实验结果显示,学生能够有效掌握并运用这些知识完成指定任务。
81 4
|
4月前
|
算法 程序员 索引
数据结构与算法学习七:栈、数组模拟栈、单链表模拟栈、栈应用实例 实现 综合计算器
栈的基本概念、应用场景以及如何使用数组和单链表模拟栈,并展示了如何利用栈和中缀表达式实现一个综合计算器。
72 1
数据结构与算法学习七:栈、数组模拟栈、单链表模拟栈、栈应用实例 实现 综合计算器
|
8月前
|
存储 算法
【数据结构和算法】--队列的特殊结构-循环队列
【数据结构和算法】--队列的特殊结构-循环队列
48 0
|
4月前
|
存储 算法 定位技术
数据结构与算法学习二、稀疏数组与队列,数组模拟队列,模拟环形队列
这篇文章主要介绍了稀疏数组和队列的概念、应用实例以及如何使用数组模拟队列和环形队列的实现方法。
50 0
数据结构与算法学习二、稀疏数组与队列,数组模拟队列,模拟环形队列
|
4月前
|
存储
【初阶数据结构】深入解析循环队列:探索底层逻辑
【初阶数据结构】深入解析循环队列:探索底层逻辑
|
5月前
|
存储 Java
java数据结构,线性表顺序存储(数组)的实现
文章介绍了Java中线性表顺序存储(数组)的实现。线性表是数据结构的一种,它使用数组来实现。文章详细描述了线性表的基本操作,如增加、查找、删除、修改元素,以及其他操作如遍历、清空、求长度等。同时,提供了完整的Java代码实现,包括MyList接口和MyLinearList实现类。通过main函数的测试代码,展示了如何使用这些方法操作线性表。