实用指南:[数据结构] 队列实战!火车车厢重排从 0 到 1:缓冲轨巧用 + 可运行代码

news/2025/11/10 14:19:32/文章来源:https://www.cnblogs.com/tlnshuju/p/19206904

实用指南:[数据结构] 队列实战!火车车厢重排从 0 到 1:缓冲轨巧用 + 可运行代码

2025-11-10 14:14  tlnshuju  阅读(0)  评论(0)    收藏  举报

队列实战!火车车厢重排从0到1:缓冲轨巧用+可运行代码(附测试验证)

刚做队列应用实验时,我对着火车车厢重排的示意图卡了好久:入轨、缓冲轨、出轨三个队列到底怎么配合?明明车厢编号是1~9的连续数,却不知道什么时候该把车厢暂存到缓冲轨,什么时候该输出到出轨,连“3692471850”这个测试用例都跑不出123456789的结果。后来才发现,核心就是利用队列“先进先出”的特性,让缓冲轨当“临时仓库”,每一步都盯着“下一个要出的编号”(nowOut)来运行。

今天就把这份《算法与数据结构》的解题思路拆成“新手友好版”,从转轨站结构讲到代码落地,再到实测验证,全程大白话+可复制代码,确保你跟着做就能跑通车厢重排。

一、实验核心:要解除啥问题?转轨站咋工作?

实验题目:火车车厢重排。实验说明:转轨站示意图如下:

在这里插入图片描述火车车厢重排过程如下:
在这里插入图片描述
火车车厢重排算法伪代码如下:
在这里插入图片描述

1. 实验目标

给定一组连续编号(1~n)但顺序打乱的火车车厢(比如3、6、9、2、4、7、1、8、5),用队列模拟“转轨站”,把车厢重排成1、2、3…n的顺序,最终从“出轨”输出。

2. 转轨站结构(关键!先看懂再写代码)

实验里的转轨站有3类队列,作用各不相同,对应代码里的H1、H2、H3:

队列类型代码中的队列作用
入轨H3存放刚开始打乱的车厢序列(比如输入的369247185)
缓冲轨H1、H2暂存暂时不能输出到出轨的车厢,必须保证车厢编号大于队尾(比如H1队尾是2,只能放3、4…,后续才能有序出队)
出轨无单独队列最终输出有序车厢的“通道”,输出一个,下一个要输出的编号(nowOut)就+1

二、核心解题思路(3步走,大白话版)

整个重排逻辑围绕“下一个要输出的编号(nowOut)”展开,nowOut初始为1(第一个要输出的是1),然后循环处理直到所有队列都空:

步骤1:初始化准备

步骤2:循环处理车厢(核心逻辑)

遍历H3(入轨),每一步做3件事:

  1. 判断入轨队头能不能直接出:如果H3的队头编号 == nowOut,直接输出到出轨,nowOut+1(比如nowOut=1时,H3队头是1就输出,nowOut变2);
  2. 判断缓冲轨队头能不能出:若是H1或H2的队头 == nowOut,输出该车厢,nowOut+1(比如nowOut=2时,H2队头是2就输出);
  3. 入轨车厢放进缓冲轨:假设前两步都不能出,就把H3的队头放进H1或H2——要求是“车厢编号 > 缓冲轨队尾”(空缓冲轨可以直接放),保证后续能有序出队(比如H1队尾是3,只能放4、5…)。

步骤3:直到所有队列空

重复步骤2,直到H3(入轨)、H1(缓冲轨1)、H2(缓冲轨2)都为空,此时出轨已经输出1、2、3…n的有序序列。

三、完整代码实现(补全原文错误,附详细注释)

原文代码有小问题(比如队列初始化没设front、return θ笔误),这里已修正,新手可直接复制运行:

#include <stdio.h>#define MAXSIZE 100  // 队列最大容量,足够应对实验需求typedef int SElemType;  // 车厢编号类型(整数)typedef int Status;     // 函数返回状态(0=失败,1=成功)// 队列结构体(顺序队列)typedef struct Queue {SElemType data[MAXSIZE];  // 存车厢编号int front;               // 队头指针(出队从front)int rear;                // 队尾指针(入队从rear)} Queue;// 1. 初始化队列(front和rear都设0,代表空队列)void InitQueue(Queue *q) {q->front = 0;    // 原文漏了front初始化,必须加上!q->rear = 0;// data[0]初始化没必要,队列用front和rear控制,不是靠data[0]}// 2. 入队(把编号num放进队列q)Status EnQueue(Queue *q, SElemType num) {// 队列满的判断:rear到最大容量-1(留一个位置防溢出,也可设为rear >= MAXSIZE)if (q->rear >= MAXSIZE - 1) {printf("队列满了,无法入队!\n");return 0;  // 原文是θ,修正为0}q->data[q->rear] = num;  // 队尾放元素q->rear++;               // 队尾后移return 1;}// 3. 出队(把队列q的队头元素存到num,成功返回1)Status DeQueue(Queue *q, SElemType* num) {// 队列空的判断:front == rearif (q->front >= q->rear) {// printf("队列空了,无法出队!\n");return 0;}*num = q->data[q->front];  // 取队头元素q->front++;                // 队头后移return 1;}// 4. 取队头元素(只看,不出队,存到num)Status GetHead(Queue *q, SElemType* num) {if (q->front >= q->rear) {return 0;}*num = q->data[q->front];return 1;}// 5. 取队尾元素(只看,不出队,存到num)Status GetRear(Queue *q, SElemType* num) {if (q->front >= q->rear) {return 0;}*num = q->data[q->rear - 1];  // 队尾是rear-1(因为rear指向空位置)return 1;}// 主函数:火车车厢重排逻辑int main() {Queue H1, H2, H3;  // H1=缓冲轨1,H2=缓冲轨2,H3=入轨InitQueue(&H1);InitQueue(&H2);InitQueue(&H3);Queue* bufferQueues[] = {&H1, &H2};  // 缓冲轨数组,方便循环遍历// 1. 输入打乱的车厢编号(输入0停止)printf("请输入火车车厢编号(连续整数,输入0停止):\n");SElemType inputNum;while (1) {scanf("%d", &inputNum);if (inputNum == 0) {break;  // 输入0结束}EnQueue(&H3, inputNum);  // 放入入轨H3}// 2. 初始化下一个要输出的车厢编号(从1开始)int nowOut = 1;printf("\n出轨输出序列:");// 循环处理:入轨、缓冲轨都为空才结束while (H3.front < H3.rear || H1.front < H1.rear || H2.front < H2.rear) {int isOutput = 0;  // 标记本次是否有车厢输出到出轨SElemType tempNum;  // 临时存车厢编号// 步骤1:判断入轨H3的队头能不能直接输出if (GetHead(&H3, &tempNum) && tempNum == nowOut) {DeQueue(&H3, &tempNum);  // 出队printf("%d ", tempNum);   // 输出到出轨nowOut++;                 // 下一个要输出的编号+1isOutput = 1;}// 步骤2:如果入轨不能出,看缓冲轨(H1、H2)的队头能不能出else {for (int i = 0; i < 2; i++) {  // 遍历两个缓冲轨if (GetHead(bufferQueues[i], &tempNum) && tempNum == nowOut) {DeQueue(bufferQueues[i], &tempNum);printf("%d ", tempNum);nowOut++;isOutput = 1;break;  // 输出一个即可,下一轮再判断其他}}}// 步骤3:如果都不能出,把入轨H3的队头放进合适的缓冲轨if (!isOutput) {GetHead(&H3, &tempNum);  // 取入轨当前要处理的车厢SElemType bufferRear;    // 缓冲轨的队尾编号// 遍历缓冲轨,找能放的(空缓冲轨 或 车厢编号>缓冲轨队尾)for (int i = 0; i < 2; i++) {if (bufferQueues[i]->front == bufferQueues[i]->rear) {  // 缓冲轨空DeQueue(&H3, &tempNum);EnQueue(bufferQueues[i], tempNum);break;} else {  // 缓冲轨非空,判断是否大于队尾GetRear(bufferQueues[i], &bufferRear);if (tempNum > bufferRear) {DeQueue(&H3, &tempNum);EnQueue(bufferQueues[i], tempNum);break;}}}}}printf("\n车厢重排完成!\n");return 0;}

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

四、运行测试:实测验证(和实验结果一致)

测试用例:输入3 6 9 2 4 7 1 8 5 0(输入0停止)

五、新手避坑指南(我踩过的坑,你别踩)

  1. 缓冲轨放车厢必须“大于队尾”
    比如H1队尾是2,不能放1!否则1永远在2后面,当nowOut=1时,H1队头是2,1出不来,最后重排失败。这是实验的核心规则,必须遵守。

  2. 队列初始化要设front=0
    原文代码的InitQueue只设了rear=0,漏了front=0,导致队列判断空/满出错,必须补上q->front=0

  3. nowOut要及时自增
    每次输出一个车厢后,一定要nowOut++,否则会一直重复输出同一个编号(比如一直找1,找到后不+1,下次还找1)。

  4. 入轨遍历要“先判后出”
    处理入轨车厢时,先通过GetHead判断能不能出,再用DeQueue出队,不能直接DeQueue后再判断,否则会把不该出的车厢删掉。

六、总结:队列的核心价值&优化方向

1. 队列在实验中的作用

2. 时间复杂度说明

原文提到“时间复杂度较高”,主要是因为每次处理都要遍历缓冲轨(H1、H2),最坏情况下时间复杂度是O(n*k)(n是车厢数,k是缓冲轨数)。优化方向可以是“记录缓冲轨队尾最大值”,不用每次遍历找合适的缓冲轨,减少循环次数。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/961373.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Kerberos常见工具错误解析与修复指南

本文详细解析了在Kerberos攻击过程中可能遇到的各种错误代码,包括KDC错误和KRB错误,提供了错误原因分析和修复方案,并包含域SID参考表,帮助安全研究人员更好地进行漏洞挖掘和渗透测试。常见工具错误 - Kerberos 当…

Vector驱动安装问题解决方案

问题描述驱动安装完成后显示部分组件未安装成功解决方案1.关闭防火墙、杀毒软件等,尝试重新卸载并安装驱动;2.如果上述方式无法解决,可以将Windows安全中心应用的浏览器和应用控制里的设置全关了,全关后需要重启电…

提取快速关闭选项卡的浏览器访问的链接

win11下,微信文件传输助手在chrome下 版本 141.0.7390.123(正式版本) (64 位)点击发送来的文件,新选项卡打开后,快速关闭,导致无法下载文件。 可以在终端使用如下获得网址链接(function() {const originalOpen…

2025年苏式月饼礼盒供货厂家权威推荐榜单:五仁月饼/礼盒月饼/月饼价格源头厂家精选

在传统节日文化与现代消费需求深度融合的背景下,苏式月饼礼盒凭借其独特的酥皮工艺、丰富的文化内涵及精美的包装设计,已成为中秋消费市场的重要组成部分。行业数据显示,2024年全球五仁月饼市场规模达亿元级别,其中…

Linux挂载硬盘操作手册

环境:银河麒麟服务器操作系统,新增/dev/sdb 需求:需要把sdb挂载到/data目录下 1.查看硬盘配置信息 输入lsblk查看硬盘配置 2.创建磁盘分区:parted /dev/sdb输入lsblk查看新建分区 3.格式化新分区 输入blkid查看sda…

常见的 Node Conditions 和

常见的 Node Conditions 每个 Condition 都有以下几个关键字段:type:条件的类型。常见的有:Ready:这是最重要的一个条件。如果为 True,表示节点健康并可以接收 Pod;如果为 False,表示节点不健康,不会调度新的 …

Print Article-斜率优化dp

HDU - 3507 Print Article $$ \begin{align} dp_i &= \min_{j=1}{i-1}(dp_j+(sum_i-sum_j)2+m) \ dp_i &= dp_j +sum_i2+sum_j2-2sum_isum_j+m \ dp_j+sum_j^2 &= 2sum_isum_j+dp_i-sum_i^2-m\ y&=kx+…

HT-LFCG-3400+,0改版,测试数据贴图

HT-LFCG-3400+,0改版,测试数据贴图成都恒利泰的HT-LFCG-3400+,官方口号是Pin-to-Pin替代,今天到手立刻上板。 实测结果先放这里: 插损:0.89 dB@2.4 GHz,比旧料还好0.1 dB; 抑制:4.5 GHz直接-36 dB,余量满满;…

C# 基础——async/await 的实现原理与最佳实践

在C#中,async/await是简化异步编程的语法糖,其核心目标是让异步代码的编写和阅读方式接近同步代码,同时避免“回调地狱”(Callback Hell)。理解其实现原理能帮助开发者写出高效、无死锁的异步代码,而遵循最佳实践…

跳房子 P3957: 单调队列

#include <bits/stdc++.h> #define int long long using namespace std; constexpr int maxn = 5e5+10; constexpr int INF = 0x3f3f3f3f3f3f3f3f;int wi[maxn],di[maxn]; int q[maxn]; // 降序单调队列 int …

P3622 动物园-状压

P3622 动物园-状压 [APIO2007] 动物园 题目大意 问题描述: 有一个环形动物园,共有 N 个围栏(环形排列),每个围栏里有一种动物。有 C 个小朋友,每个小朋友会从某个围栏 E 开始,连续看到 5 个围栏(顺时针方向)。…

candy P14328: dp优化

P14328 [JOI2022 预选赛 R2] 糖 2 / Candies 2 题解 题目链接:p14328 题意描述 有 $N$ 个糖果排成一列,每个糖果有一个美味度 $A_i$。需要选择糖果,使之满足限制:对于任意连续的 $K$ 个糖果,最多只能选择其中 $2$…

配对序列P11187: 线性dp

原题 #include <bits/stdc++.h> #define int long long using namespace std; constexpr int maxn = 5e5+10; constexpr int maxm = 2e6+10;int n; int wi[maxn]; int dp[maxn][2]; // 题目要求:奇数为和下一个…

2025年新疆广告公司权威推荐榜单:geo服务商/广告加盟/营销推广公司机构精选

在数字经济与AI技术深度融合的今天,选对广告营销合作伙伴,已成为企业抢占新疆及全国市场的关键一步。 随着数字营销生态的快速演进,新疆广告行业正经历着深刻变革。根据行业分析报告,2025年中国数字营销市场规模预…

计算机毕设java的仓库管理系统 基于Java的智能仓库管理平台研发 Java技术驱动的仓库信息化管理系统设计与实现

pre { white-space: pre !important; word-wrap: normal !important; overflow-x: auto !important; display: block !important; font-family: "Consolas", "Monaco", "Courier New", …

吴恩达深度学习课程二: 改善深层神经网络 第二周:优化算法(三)Momentum梯度下降法

此分类用于记录吴恩达深度学习课程的学习笔记。 课程相关信息链接如下:原课程视频链接:[双语字幕]吴恩达深度学习deeplearning.ai github课程资料,含课件与笔记:吴恩达深度学习教学资料 课程配套练习(中英)与答案…