问题节选自<<数据结构、算法与应用(C++语言描述)>>, 思路与代码为原创, 如有疏漏及问题欢迎指正

问题描述:

一辆列车有n节车厢, 车厢排列乱序(如: 284657139), 但整体车厢序号连续(序号整体没有断), 每节车厢要停靠不同的站台.

现有n个车站从1到n编号, 列车按照从1到n的顺序经过车站, 列车要在车厢号和车站号相同时, 将车厢卸下, 为了便于卸载, 需

要将车厢重新顺序排列. 重排后列车只需每次卸下最后一节车厢即可, 为了方便重排, 现有入轨道, 出轨道以及三个缓冲轨道,

规定列车从入轨道入, 可将当前入轨车厢转入缓冲轨道或直接移至出轨道, 缓冲轨道中的车厢可按从后至前的顺序移至出轨

道, 列车出轨道后即完成重排.

抽象:

即现有一顺序混乱的栈结构, 要将栈内元素重排, 有三个缓冲栈和一个重排后的结果栈

思路:

第一步: 用一变量记录当前结果栈需要的元素值, 之后初始栈元素顺序出栈, 出栈同时判断是否是结果栈所需要的元素, 是则直接

加入结果栈并将当前记录值减一, 否则将元素推入缓冲栈.

第二步: 元素入缓冲栈时对三个缓冲栈从左至右进行检查, 若栈为空, 直接将元素入栈, 否则判断当前栈的栈顶元素值是否小于当

前元素, 是则推入栈中, 否则跳至下一缓冲栈进行检查.

第三步: 对当前三个缓冲栈进行检查, 若当前三个缓冲栈中任意一栈的栈顶元素满足结果栈需求, 将该元素加入结果栈并将记录值

减一, 重复当前步骤, 直至缓冲栈栈顶元素均不满足要求.

重复以上三步即可完成重排

代码如下:

 #include <iostream>
#include <stack>
#include <vector> #define BUFFER_COUNT 2
#define BUFFER_START 0 static int train_number = ; //当前重排列车需求 std::vector<std::stack<int>> vec_buffer_stack; //缓冲轨道
std::stack<int> train; //初始列车
std::stack<int> rearrange_train; //重排列车 void train_init()
{
train.push();
train.push();
train.push();
train.push();
train.push();
train.push();
train.push();
train.push();
train.push();
} void check_train()
{
if (train.empty())
{
return;
} //当前出栈元素符合重排需求,加入重排列车
if (train.top() == train_number)
{
std::cout << "from current train, rearrange train input " << train.top() << std::endl; rearrange_train.push(train.top());
train.pop();
--train_number;
}
} void check_buffer()
{
for (size_t i = BUFFER_START; i <= BUFFER_COUNT; ++i)
{
if (!vec_buffer_stack[i].empty())
{
//缓冲轨道中车厢符合重排需求,车厢加入重排列车
if (vec_buffer_stack[i].top() == train_number)
{
std::cout << "from buffer " << i << ", rearrange train input " << vec_buffer_stack[i].top() << std::endl; rearrange_train.push(vec_buffer_stack[i].top());
vec_buffer_stack[i].pop();
--train_number; //继续检查缓冲轨道
check_buffer();
break;
}
}
}
} void push_train()
{
if (train.empty())
{
return;
}
for (size_t i = BUFFER_START; i <= BUFFER_COUNT; ++i)
{
//缓冲轨道为空,直接将车厢加入
if (vec_buffer_stack[i].empty())
{
std::cout << "buffer " << i << " push " << train.top() << std::endl; vec_buffer_stack[i].push(train.top());
train.pop(); break;
}
//车厢序号大于缓冲轨道尾车厢序号,加入当前车厢
else if (train.top() > vec_buffer_stack[i].top())
{
std::cout << "buffer " << i << " push " << train.top() << std::endl; vec_buffer_stack[i].push(train.top());
train.pop(); break;
}
}
} void rearrange_curr_train()
{
//检查当前结果栈需求车厢号
while (train_number != )
{
//车厢出栈检查
check_train(); //车厢加入缓存
push_train(); //缓存检查
check_buffer();
} }

测试

C++ 解决列车重排问题的更多相关文章

  1. BFS解决九宫重排问题

    问题 1426: [蓝桥杯][历届试题]九宫重排 时间限制: 1Sec 内存限制: 128MB 提交: 215 解决: 47 题目描述 如下面第一个图的九宫格中,放着  1~8  的数字卡片,还有一个 ...

  2. 手淘架构组最新实践 | iOS基于静态库插桩的⼆进制重排启动优化 抖音研发实践:基于二进制文件重排的解决方案 APP启动速度提升超15% 编译期插桩

    抖音研发实践:基于二进制文件重排的解决方案 APP启动速度提升超15% 原创 Leo 字节跳动技术团队 2019-08-09 https://mp.weixin.qq.com/s/Drmmx5JtjG ...

  3. C++11的原子量与内存序浅析

    一.多线程下共享变量的问题 在多线程编程中经常需要在不同线程之间共享一些变量,然而对于共享变量操作却经常造成一些莫名奇妙的错误,除非老老实实加锁对访问保护,否则经常出现一些(看起来)匪夷所思的情况.比 ...

  4. Java 内存模型 ,一篇就够了!

    Java 虚拟机   我们都知道 Java 语言的可以跨平台的,这其中的核心是因为存在 Java 虚拟机这个玩意.虚拟机,顾名思义就是虚拟的机器,这不是真实存在的硬件,但是却可以和不同的底层平台进行交 ...

  5. The All-in-One Note

    基础 操作系统 I/O 模型 阻塞式 I/O 模型(blocking I/O) 描述:在阻塞式 I/O 模型中,应用程序在从调用 recvfrom 开始到它返回有数据报准备好这段时间是阻塞的,recv ...

  6. Java Volatile关键字(转)

    出处:  Java Volatile关键字 Java的volatile关键字用于标记一个变量“应当存储在主存”.更确切地说,每次读取volatile变量,都应该从主存读取,而不是从CPU缓存读取.每次 ...

  7. Java锁机制深入理解

    Java锁机制 背景知识 指令流水线 ​ CPU的基本工作是执行存储的指令序列,即程序.程序的执行过程实际上是不断地取出指令.分析指令.执行指令的过程. ​ 几乎所有的冯•诺伊曼型计算机的CPU,其工 ...

  8. Java 内存模型都不会,就敢在简历上写熟悉并发编程吗

    从 PC 内存架构到 Java 内存模型 你知道 Java 内存模型 JMM 吗?那你知道它的三大特性吗? Java 是如何解决指令重排问题的? 既然CPU有缓存一致性协议(MESI),为什么 JMM ...

  9. Java并发编程 (五) 线程安全性

    个人博客网:https://wushaopei.github.io/    (你想要这里多有) 一.安全发布对象-发布与逸出 1.发布与逸出定义 发布对象 : 使一个对象能够被当前范围之外的代码所使用 ...

随机推荐

  1. 多级反向代理java获取真实IP地址

    public static String getIpAddress(HttpServletRequest request){ String ip = request.getHeader("x ...

  2. javaweb-codereview 学习记录-4

    反射java.lang.Runtime 之前在p牛的知识星球中也学过反射机制调用Runtime来执行命令时需要用getruntime来返回Runtime类的实例,因为Runtime类设计是单例模式,并 ...

  3. ELK实战-elasticsearch安装

    操作系统: centos版本 7.4 防火墙 关闭 selinux 关闭 elasticsearch版本 6.3.2 java版本 1.8 server1 192.168.10.126 server2 ...

  4. GP工作室—需求分析

    团队作业第二次作业--需求分析 问题 答案 这个作业属于哪个课程 软件工程 这个作业要求在哪里 作业要求 团队名称 GP工作室 这个作业的目标 ① 团队项目的需求分析 ②团队项目的原型设计 团队队员介 ...

  5. c#数字图像处理(十二)图像的腐蚀与膨胀

    背景知识 腐蚀与膨胀基本原理:就是用一个特定的结构元素来与待处理图像按像素做逻辑操作:可以理解成拿一个带孔的网格板(结构元素矩阵中元素为1的为孔)盖住图像的某一部分,然后按照各种不同的观察方式来确定操 ...

  6. linux--->Linux centon6.9 安装mysql

    Linux centon6.9 安装mysql 查看系统自带的安装包 yum list installed | grep mysql 2.上边显示有mysql 有5.1和5.5两个版本,我安装5.5 ...

  7. 痞子衡嵌入式:知名半导体MCU大厂软件开发C代码规范

    大家好,我是痞子衡,是正经搞技术的痞子.今天痞子衡给大家讲的是飞思卡尔软件开发C语言编码规范. 2020鼠年春节是个漫长的假期,痞子衡在家百无聊赖,翻出了2016年10月1日(这个时间是痞子衡正式开始 ...

  8. Jutil 单元测试

    eclipse 自身集成了jtuil,右击项目,点击bulidpath,addjar,如下所示添加jutil 新建一个Junit的测试类用来测试上面的测试方法,新增Junit的测试类方法如下: // ...

  9. Android Studio中Gradle sync failed

    问题:Android Studio中更新同步Gradle 失败 Gradle sync failed: Could not find com.android.tools.build:gradle:3. ...

  10. Java 中的运算符和流程控制

    Java 中的运算符和流程控制 + 面试题 算术运算符 Java 中的算术运算符,包括以下几种: **算术运算符** **名称** **举例** + 加法 1+2=3 - 减法 2-1=1 \* 乘法 ...