Day12

今天学算法与数据结构:被“队列”的“假溢出”上了一课

课前翻课本时,看到“队列”的定义写着“先进先出(FIFO)”,心里还嘀咕:这不就是比栈多换个规则吗?结果跟着老师动手实现时才发现,这“排队”的逻辑里,藏着我没料到的“坑”。

老师开篇没讲代码,先在黑板上画了个买奶茶的队伍:第一个来的人先点单,后面的人排着,没人会插队,也没人会跳过前面的人——这就是队列的“FIFO”。我当时觉得“这也太好理解了”,直到老师让我们用数组写一个简单队列:定义int[] arr存元素,front指针指向队头,rear指针指向队尾,enqueue就是把元素放rear位置再后移,dequeue就是取front位置元素再后移。

我很快敲完代码,测试时先往队列里加了3个元素(arr长度设为5),然后取走2个,这时候队列里只剩1个元素,front移到了索引2的位置。可当我再想加2个元素时,rear已经到了索引4(数组末尾),直接报错“队列满了”。我盯着屏幕纳闷:明明数组前面还有2个空位(索引0和1),怎么就满了?

“这就是数组队列的‘假溢出’。”老师走过来指着我的代码说,“你现在的判断条件是rear == arr.length - 1就认为满了,但实际上队头前面有空位,只是rear到了末尾,没法往后移了。”接着他在黑板上画了个循环的箭头,说“要解决这个问题,得让队列‘循环’起来——当rear到末尾时,如果前面有空位,就绕回开头。”

然后老师教我们改代码:把enqueue里的rear++改成rear = (rear + 1) % arr.length,判断队列满的条件也换成(rear + 1) % arr.length == front。我照着改完再测试:刚才的情况里,rear到4后,再加元素时,(4+1)%5=0,正好绕回索引0的位置,之前的空位就用上了。原来队列的“循环”不是真的把数组弯成圈,而是用取模运算让指针“绕着走”,这一下就解决了“假溢出”的问题。

后来老师还提了队列的应用,比如任务调度:后台处理请求时,按收到的顺序排队,一个一个处理,不会乱序;还有BFS(广度优先搜索),比如找图里从A到B的最短路径,就得用队列存每一层的节点。虽然BFS没细讲,但我看着自己写的循环队列代码突然懂了:数据结构的设计不是“为了复杂而复杂”,比如循环队列就是为了解决数组队列的“假溢出”问题,每一个优化都对应着实际场景的需求。

课堂练习时,老师让我们用循环队列模拟“打印机任务”:有3个打印任务依次进入队列,打印机先处理第一个,处理完再取下一个。我照着循环队列的逻辑写,这次没再犯“假溢出”的错,甚至还加了个“查看队头任务”的方法,看着控制台一步步输出“任务1入队→任务2入队→任务1处理完成→任务2处理完成”,突然觉得“队列”不再是课本上的四个字,而是能实实在在模拟现实场景的工具。

下课前翻着草稿本上的循环队列示意图,frontrear在数组里“绕圈”的样子还很清晰。原来学数据结构,不是记“先进先出”这种干巴巴的定义,而是要懂“为什么会有这个结构”“它的问题在哪”“怎么优化”——就像今天的队列,从简单数组到循环队列,每一步都是为了解决实际用的时候遇到的麻烦。

晚上打算再用链表实现一次队列,对比下数组循环队列和链表队列的区别:比如数组要提前定长度,链表可以动态扩容,各有各的用处。看来算法与数据结构这门课,得带着“解决问题”的思路学,才不会觉得抽象。

posted @ 2025-10-16 22:11  晨乌  阅读(1)  评论(0)    收藏  举报