002队列 - 先进先出的线性结构
队列 - 先进先出的线性结构
什么是队列?
📰 5W1H 发明者故事
Who(何人)- 发明者是谁?
发明者:约翰·冯·诺依曼(John von Neumann)和早期计算机科学家们
背景:冯·诺依曼(1903-1957),匈牙利裔美国数学家,普林斯顿高等研究院教授,被誉为"现代计算机之父"。他的博学令人叹为观止——从集合论到量子力学,从博弈论到弹道计算,无所不通。
当时的处境:1950年代,计算机开始被用于处理批量任务。程序员发现,很多现实问题——打印机作业排队、网络包缓冲、进程调度——都需要一种能按顺序"公平"处理的数据结构。冯·诺依曼在设计存储程序计算机时,就意识到了"有序等待"这一模式的重要性。
When(何时)- 什么时候发明的?
时间:1940年代末—1950年代初
时代背景:
- 冯·诺依曼体系结构(1945年)刚刚确立
- 早期操作系统雏形出现,批处理作业排队是核心问题
- 计算机从军用研究走向商业应用(IBM 701,1952年)
- 多任务、多用户计算的需求开始出现
- "先到先服务"被认为是最公平的调度原则
Where(何地)- 在哪里发明的?
地点:美国新泽西州普林斯顿高等研究院(IAS)
环境:二战后的美国,科学研究经费充裕,政府希望计算机能处理大量科学计算和行政事务。IAS计算机项目汇聚了当时最聪明的数学家和工程师,他们既要解决硬件问题,也要解决软件调度问题。
What(何事)- 发明了什么?
数据结构:队列(Queue)
核心概念:像排队买票一样,先到的先服务——“先进先出”(FIFO: First In First Out)。新来的人排在队伍尾部,服务完成后从队伍头部离开。
关键突破:
- 公平性原则:保证数据按到达顺序被处理,不发生饥饿
- 双端管理:一端(队尾)负责入队,另一端(队头)负责出队
- 缓冲器模型:生产者-消费者之间的解耦机制
- 循环实现:用环形数组避免空间浪费
Why(何因)- 为什么发明?
要解决的问题:
- 批处理调度:多个程序等待CPU执行,必须有一种公平的排队机制
- I/O缓冲:打印机、磁带读写速度远低于CPU,需要缓冲队列
- 广度优先搜索:图遍历时需要按层次顺序访问节点
- 网络数据包:路由器需要按到达顺序转发数据包
当时的挑战:
- 内存极其稀缺,不能为队列预留太多空间
- 数组实现的队列会产生"假满"问题(数据不断后移,头部浪费)
- 需要O(1)的入队和出队操作
动机:现实世界中大量的"等待"模型——银行排队、工厂流水线、邮局取号——都符合先进先出的规律。将这种日常逻辑形式化为数据结构,是一个自然而然的抽象。
How(何果)- 如何实现?有什么影响?
实现思路:
- 用数组存储元素,维护头指针(front)和尾指针(rear)
- 入队:rear指针加1,存入数据
- 出队:取出front处数据,front指针加1
- 循环队列:用取模运算避免数组越界,实现"环形"复用
技术方案:
循环队列(容量5):
索引: [0] [1] [2] [3] [4]
数据: [A] [B] [C] [ ] [ ]
↑ ↑
front rear
入队D:rear=(3+1)%5=3,data[3]=D
出队:取data[1]=B,front=(1+1)%5=2
历史影响:
- 操作系统的进程调度队列(就绪队列、等待队列)
- 网络协议栈的数据包缓冲
- 广度优先搜索(BFS)的核心数据结构
- 生产者-消费者模型的基础
- 消息队列系统(RabbitMQ、Kafka)的理论根基
今天的使用:
- CPU任务调度(时间片轮转)
- 键盘/鼠标事件队列
- Web服务器的请求队列
- 打印机缓冲队列
📝 自然语言需求定义
需求名称:实现循环队列,支持先进先出(FIFO)操作
功能需求(用精确的中文描述)
-
初始化队列:创建一个指定容量的空队列
- 输入:最大容量(正整数)
- 操作:分配内存,初始化头尾指针
- 输出:队列指针,失败返回NULL
-
入队(Enqueue):将元素加入队尾
- 输入:队列指针,要加入的整数
- 操作:检查队列是否已满,未满则在rear位置存入数据,rear前进一位
- 输出:成功返回true,失败(队满)返回false
-
出队(Dequeue):从队头取出元素
- 输入:队列指针
- 操作:检查队列是否为空,非空则取出front处数据,front前进一位
- 输出:成功返回true,数据通过指针参数返回;失败返回false
-
查看队头(Front):查看但不取出队头元素
- 输入:队列指针
- 操作:返回front处的元素值,不移除
- 输出:成功返回true;失败(队空)返回false
-
获取队列大小:返回当前队列中元素个数
- 输入:队列指针
- 输出:元素个数,空队列返回0
约束条件
- 使用循环数组(取模运算)实现,避免假满问题
- 队满条件:(rear + 1) % capacity == front
- 队空条件:front == rear
- 所有操作时间复杂度O(1)
- 循环队列实际存储容量为 capacity-1(预留一格区分满/空)
验收标准(必须可验证)
| 编号 | 测试场景(自然语言描述) | 预期结果 | 验证方式 |
|---|---|---|---|
| 1 | 创建容量为5的队列 | 队列为空,大小为0 | 检查is_empty和size |
| 2 | 入队10,20,30 | 队列大小为3,队头为10 | 检查size和front值 |
| 3 | 出队一次 | 返回10,新队头为20,大小变为2 | 检查返回值、front和size |
| 4 | 队列填满后继续入队 | 返回false,队列内容不变 | 填满后再enqueue,检查返回值 |
| 5 | 空队列出队 | 返回false,不崩溃 | 空队列dequeue,检查返回值 |
| 6 | 先出队再入队(利用循环特性) | 正确利用前段空间,操作成功 | 出队2次后再入队,验证循环复用 |
| 7 | 连续入队出队直到为空 | 最终队列为空,所有数据顺序正确 | 批量操作验证FIFO属性 |
AI 生成提示
基于以上需求和验收标准,用标准C语言实现循环队列。
要求:
1. 使用标准C99
2. 结构体包含:data数组、front、rear、capacity字段
3. 用取模运算实现循环特性
4. 包含完整错误处理(NULL检查、满/空检查)
5. 内存安全(malloc/free配对)
6. 代码必须有详细注释
7. 在main函数中实现所有7个验收标准的测试用例
核心函数:
- init_queue(capacity) - 初始化
- enqueue(queue, value) - 入队
- dequeue(queue, &value) - 出队
- front(queue, &value) - 查看队头
- is_empty(queue) - 是否为空
- is_full(queue) - 是否已满
- queue_size(queue) - 获取大小
- free_queue(queue) - 释放内存
💻 C语言实现文件
对应文件: queue.c
编译运行:
gcc -o queue_test queue.c
./queue_test
核心函数:
init_queue(capacity)- 初始化循环队列enqueue(queue, value)- 入队dequeue(queue, &value)- 出队front_val(queue, &value)- 查看队头is_empty(queue)- 判断是否为空queue_size(queue)- 获取大小free_queue(queue)- 释放内存
openEuler 是由开放原子开源基金会孵化的全场景开源操作系统项目,面向数字基础设施四大核心场景(服务器、云计算、边缘计算、嵌入式),全面支持 ARM、x86、RISC-V、loongArch、PowerPC、SW-64 等多样性计算架构
更多推荐

所有评论(0)