洛谷 P1827 [USACO3.4]美国血统 American Heritage C++ 二叉树基础

本文主要是介绍洛谷 P1827 [USACO3.4]美国血统 American Heritage C++ 二叉树基础,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

题目描述

农夫约翰非常认真地对待他的奶牛们的血统。然而他不是一个真正优秀的记帐员。他把他的奶牛 们的家谱作成二叉树,并且把二叉树以更线性的“树的中序遍历”和“树的前序遍历”的符号加以记录而 不是用图形的方法。

你的任务是在被给予奶牛家谱的“树中序遍历”和“树前序遍历”的符号后,创建奶牛家谱的“树的 后序遍历”的符号。每一头奶牛的姓名被译为一个唯一的字母。(你可能已经知道你可以在知道树的两 种遍历以后可以经常地重建这棵树。)显然,这里的树不会有多于 26 个的顶点。 这是在样例输入和 样例输出中的树的图形表达方式:

         C/  \/  \B    G/ \  /A   D  H/ \E   F

树的中序遍历是按照左子树,根,右子树的顺序访问节点。

树的前序遍历是按照根,左子树,右子树的顺序访问节点。

树的后序遍历是按照左子树,右子树,根的顺序访问节点。

输入格式

第一行: 树的中序遍历

第二行: 同样的树的前序遍历

输出格式

单独的一行表示该树的后序遍历。

输入输出样例

输入 #1复制

ABEDFCHG
CBADEFGH 

输出 #1复制

AEFDBHGC

说明/提示

题目翻译来自NOCOW。

USACO Training Section 3.4

思路简介

其实题目的意思就是,给出一个二叉树的中序遍历和前序遍历,要求出这棵树的后序遍历。下面贴出神犇对此题的详解及代码:

Diamikohttps://www.luogu.com.cn/user/203102更新时间:2020-04-06 07:39:11

在 Ta 的博客查看

这里利用到一个最重要的知识点——二叉树遍历。

  • 前序遍历:根左右

  • 中序遍历:左根右

  • 后序遍历:左右根

前序遍历是先遍历根节点,再遍历根节点的左右子树。

那么,前序序列的第一个节点,一定是根节点。

找到根节点,再确定根节点在中序序列中的位置,就可以分出左右两棵子树。

这道题我们不需要建树,只要通过递归不断切割字符串就好了。

字符串切割时应注意的问题

那便是切割位置。STL的string类型自带切割方法substr,但搞不清参数就会导致WA甚至RE。

首先我们搞清楚substr方法的使用方法。

string s;
s.substr(order,k);

参数传入一个order,一个k。

函数将会从下标为order的位置开始,连续截取k个字符。返回截取后的字符串。

order显然不能超出0~s.size()-1的范围。

但是,如果order+k超过了s.size()-1,函数会自动只截取到s的末尾。

如果不传入k,那么默认截取到末尾。

这个函数是返回一个字符串,而不是对s进行改动。

那么我们现在就开始寻找参数规律。

见下面的图(样例)

看到前序序列的第一个字符是 C ,那么根节点就是 C ,找到中序中对应的位置,数下标,发现 C 在 5 处 (注意字符串下标从0开始)

然后在先序序列中把C删掉。

这是因为我们后面不会用到了。

(下面的数字是下标)

中序序列中C在5处,那么左右子树分别就是ABEDF(0~4)和HG(6~7)。

设在中序序列中根节点的位置是k,

很容易发现:

  • 中序序列中左子树就是从0开始切割到k-1,也就是切割了k个字符;

  • 中序序列中右子树就是从k+1开始,一直切割到最后。

然后找前序序列切割的规律。

中序序列中左子树是ABEDF,右子树是HG,对应在前序序列中就是BADEF(0~4)和GH(5~6)。

那么

  • 前序序列中左子树是从0开始切割到k-1,也就是切割了k个字符;

  • 前序序列中右子树就是从k开始,一直切割到最后。

另外仍需补充的几点,是关于查找和删除。

s.find(c);
//在字符串s中查找第一个字符c的位置,返回下标,如果没有返回string::nposs.erase(it);
//在字符串中删除指针it所指向的字符s.begin();
//返回s的首字符的指针(迭代器)

那么我们现在就可以开始写代码了!

(注意代码中的pre是前序,inor是中序)

#include<string>
#include<cstring>
#include<iostream>
#include<cstdio>
using namespace std;
string pre,inor;
void work(string pre,string inor)
{if(pre.empty())return;//如果序列空了,就没必要继续了char root=pre[0];//取到前序序列的首字母,即根节点int k=inor.find(root);//找到中序序列中根节点的位置pre.erase(pre.begin());//删去前序序列中的根节点string leftpre=pre.substr(0,k);//从0开始切割k个string rightpre=pre.substr(k);//从k开始切割到最后string leftinor=inor.substr(0,k);//从0开始切割k个string rightinor=inor.substr(k+1);//从k+1开始切割到最后work(leftpre,leftinor);work(rightpre,rightinor);printf("%c",root);//因为要输出后序序列,所以是左右根//先遍历左子树,再右子树,再根节点
}
int main()
{cin>>inor>>pre;work(pre,inor);putchar('\n');return 0;
}

结束!

看完佬的基操,本蒟蒻不得不感叹自己实在是太菜了!佬们实在是太强了!%%%%%%%%

这篇关于洛谷 P1827 [USACO3.4]美国血统 American Heritage C++ 二叉树基础的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/301009

相关文章

C++中全局变量和局部变量的区别

《C++中全局变量和局部变量的区别》本文主要介绍了C++中全局变量和局部变量的区别,全局变量和局部变量在作用域和生命周期上有显著的区别,下面就来介绍一下,感兴趣的可以了解一下... 目录一、全局变量定义生命周期存储位置代码示例输出二、局部变量定义生命周期存储位置代码示例输出三、全局变量和局部变量的区别作用域

C++中assign函数的使用

《C++中assign函数的使用》在C++标准模板库中,std::list等容器都提供了assign成员函数,它比操作符更灵活,支持多种初始化方式,下面就来介绍一下assign的用法,具有一定的参考价... 目录​1.assign的基本功能​​语法​2. 具体用法示例​​​(1) 填充n个相同值​​(2)

c++ 类成员变量默认初始值的实现

《c++类成员变量默认初始值的实现》本文主要介绍了c++类成员变量默认初始值,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧... 目录C++类成员变量初始化c++类的变量的初始化在C++中,如果使用类成员变量时未给定其初始值,那么它将被

C++中NULL与nullptr的区别小结

《C++中NULL与nullptr的区别小结》本文介绍了C++编程中NULL与nullptr的区别,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编... 目录C++98空值——NULLC++11空值——nullptr区别对比示例 C++98空值——NUL

C++ Log4cpp跨平台日志库的使用小结

《C++Log4cpp跨平台日志库的使用小结》Log4cpp是c++类库,本文详细介绍了C++日志库log4cpp的使用方法,及设置日志输出格式和优先级,具有一定的参考价值,感兴趣的可以了解一下... 目录一、介绍1. log4cpp的日志方式2.设置日志输出的格式3. 设置日志的输出优先级二、Window

从入门到精通C++11 <chrono> 库特性

《从入门到精通C++11<chrono>库特性》chrono库是C++11中一个非常强大和实用的库,它为时间处理提供了丰富的功能和类型安全的接口,通过本文的介绍,我们了解了chrono库的基本概念... 目录一、引言1.1 为什么需要<chrono>库1.2<chrono>库的基本概念二、时间段(Durat

C++20管道运算符的实现示例

《C++20管道运算符的实现示例》本文简要介绍C++20管道运算符的使用与实现,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧... 目录标准库的管道运算符使用自己实现类似的管道运算符我们不打算介绍太多,因为它实际属于c++20最为重要的

Visual Studio 2022 编译C++20代码的图文步骤

《VisualStudio2022编译C++20代码的图文步骤》在VisualStudio中启用C++20import功能,需设置语言标准为ISOC++20,开启扫描源查找模块依赖及实验性标... 默认创建Visual Studio桌面控制台项目代码包含C++20的import方法。右键项目的属性:

c++中的set容器介绍及操作大全

《c++中的set容器介绍及操作大全》:本文主要介绍c++中的set容器介绍及操作大全,本文通过实例代码给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友参考下吧... 目录​​一、核心特性​​️ ​​二、基本操作​​​​1. 初始化与赋值​​​​2. 增删查操作​​​​3. 遍历方

解析C++11 static_assert及与Boost库的关联从入门到精通

《解析C++11static_assert及与Boost库的关联从入门到精通》static_assert是C++中强大的编译时验证工具,它能够在编译阶段拦截不符合预期的类型或值,增强代码的健壮性,通... 目录一、背景知识:传统断言方法的局限性1.1 assert宏1.2 #error指令1.3 第三方解决