资讯动态

【数据结构】C语言实现循环队列

发布时间:2026/10/3 22:02:43 来源:尧图企业网站定制
✨前言队列是数据结构中经典的先进先出FIFO线性结构普通顺序队列会出现「假溢出」问题而循环队列完美解决了数组队列的空间浪费问题。本文手把手带你用C语言实现静态数组版循环队列包含初始化、入队、出队、判空、判满、遍历等全套操作代码带详细注释零基础轻松看懂[TOC](文章目录)一、为什么需要循环队列1. 普通顺序队列的缺陷普通数组顺序队列进行多次入队、出队后front指针不断后移数组前面的空间无法重复使用队列看似满了实际存在大量空闲空间这种现象叫做假溢出。2. 循环队列的优化思路将数组首尾相连形成环状结构通过取模运算 %让指针移动到数组末尾后自动回到头部彻底解决假溢出问题最大化利用数组空间。二、循环队列核心原理1. 结构体设计data[]存储队列元素的数组front队首指针指向队首元素rear队尾指针指向下一个入队位置2. 核心判定公式经典留白法本文采用业界通用的牺牲一个存储位区分空/满的方式队列为空front rear队列已满(rear 1) % MAX_SIZE front队列长度(rear - front MAX_SIZE) % MAX_SIZE三、完整可运行源码纯C语言实现无多余依赖支持入队、出队、取队首、求长度、遍历打印直接复制可编译运行。#include stdio.h #include stdlib.h #define MAX_SIZE 100 // 循环队列结构体定义 typedef struct { int data[MAX_SIZE]; // 存储队列数据 int front; // 队首指针 int rear; // 队尾指针 } Queue; /** * brief 初始化循环队列 */ void initQueue(Queue *q) { q-front 0; q-rear 0; } /** * brief 判断队列是否为空 * return 1为空 0不为空 */ int isEmpty(Queue *q) { return q-front q-rear; } /** * brief 判断队列是否已满 * return 1为满 0未满 */ int isFull(Queue *q) { return (q-rear 1) % MAX_SIZE q-front; } /** * brief 入队操作 * param value 入队元素 * return 成功返回1失败返回0 */ int enqueue(Queue *q, int value) { if (isFull(q)) { printf(队列已满无法入队\n); return 0; } q-data[q-rear] value; q-rear (q-rear 1) % MAX_SIZE; return 1; } /** * brief 出队操作 * param value 保存出队元素 * return 成功返回1失败返回0 */ int dequeue(Queue *q, int *value) { if (isEmpty(q)) { printf(队列已空无法出队\n); return 0; } *value q-data[q-front]; q-front (q-front 1) % MAX_SIZE; return 1; } /** * brief 获取队首元素不删除 */ int getFront(Queue *q, int *value) { if (isEmpty(q)) { printf(队列已空\n); return 0; } *value q-data[q-front]; return 1; } /** * brief 获取当前队列有效元素个数 */ int getSize(Queue *q) { return (q-rear - q-front MAX_SIZE) % MAX_SIZE; } /** * brief 打印队列所有元素 */ void printQueue(Queue *q) { if (isEmpty(q)) { printf(队列已空\n); return; } printf(队列元素); int i q-front; while (i ! q-rear) { printf(%d , q-data[i]); i (i 1) % MAX_SIZE; } printf(\n); } // 主函数测试 int main() { Queue q; initQueue(q); // 元素入队 enqueue(q, 10); enqueue(q, 20); enqueue(q, 30); printQueue(q); // 元素出队 int value; if (dequeue(q, value)) { printf(出队元素%d\n, value); } printQueue(q); // 获取队首元素 if (getFront(q, value)) { printf(队首元素%d\n, value); } // 获取队列长度 printf(队列长度%d\n, getSize(q)); return 0; }四、函数功能逐行详解1. 队列初始化 initQueue将 front 和 rear 指针置0表示队列为空完成队列初始化所有数据位初始为默认值。2. 判空 判满循环队列最核心难点通过预留一个空位区分空和满避免歧义。如果不预留空位frontrear 无法判断是空队列还是满队列。3. 入队 enqueue先判断队列是否已满未满则将元素存入 rear 指针位置再通过取模运算更新 rear 指针实现环形移动。4. 出队 dequeue判断队列非空取出 front 指针指向的元素向后移动 front 指针完成出队遵循先进先出规则。5. 长度计算 getSize加入 MAX_SIZE 再取模是为了避免 rear front 时出现负数保证长度计算结果永远为正数。6. 队列遍历 printQueue从 front 开始遍历直到等于 rear 结束精准打印所有有效元素不打印预留空位。五、程序运行结果编译运行代码输出结果如下队列元素10 20 30 出队元素10 队列元素20 30 队首元素20 队列长度2结果解析依次入队 10、20、30队列正常存储数据出队队首 10符合先进先出特性剩余队首为20有效元素个数为2六、循环队列优缺点✅优点解决普通顺序队列假溢出问题空间利用率极高数组实现读写速度快时间复杂度 O(1)结构简单、稳定性强常用于操作系统任务队列、缓冲区❌缺点静态数组实现队列容量固定无法动态扩容需要牺牲一个存储空间用来区分空满状态七、拓展优化方向动态循环队列使用动态内存 malloc 实现可扩容队列计数器法判空满新增size变量无需牺牲存储空间链式队列解决固定容量问题支持无限扩容八、总结循环队列是数据结构面试、期末考试、工程开发中的高频考点。核心精髓就是利用取模运算实现指针环形移动解决顺序队列的空间浪费问题。本文代码完整、注释详尽、逻辑清晰非常适合新手学习、课程作业与面试复习

读完文章,也想定制专属网站?

尧图设计师 24 小时内与您沟通定制方案

免费获取报价 →
↑