已知树的先序和中序遍历,求其后序遍历问题

初见安~超级激动地自己写代码解决了这么个问题所以来发篇博客。

问题就如标题所示了。【还是放一下具体题面

Description

给出树的前序遍历及中序遍历,求其后序遍历。

Input

存在多组数据,请做到文件底结束
每组数据给出两个字符串,均不超过26个字母。分为前序、中序遍历。

Output

如题

Sample Input

DBACEGF ABCDEFG
BCAD CBAD

Sample Output

ACBFGED
CDAB

Sol

已知树的先序和中序,首先是一定可以确定一棵树的。至于如何处理,我们可以手动推一下试试。

再放一个样例——

Input2

ABDEGCF DBGEACF

Output2

DGEBFCA

首先我们第一反应——由先序遍历(根左右)可得:树的根节点为A。而中序遍历(左根右)首为D,可得:树的左半边是由A出发一路递归到了点D。而后B在先序中出现过,所以中序里的DB是在回溯;G没有在先序出现过,所以是B的右子树的内容了,E同理…………【剩下的自己去画吧。

如果这样找的话好像特判就特别多了。但是我们仔细观察上边的过程——我们一直在用中序找,以先序作为判定是根还是子树的参考。既然如此何不再简化先序的作用——用来找父亲节点。什么意思——后序遍历(左右根)的遍历方式其实类似于线段树,先左后右最后回溯至其父亲。如果我们找到了一个父亲节点,就相当于可以直接搜其两个儿子节点,遇到叶子节点直接输出即可。

可能你还是没怎么懂,我们用这个思路再找一遍吧——在上方的样例2中,首先由ABDEGCF可知根节点为A。我们发现在中序中A的下标为(从0开始)4,所以中序中[ 0,  3 ]为最大左子树,[ 5, 6 ]为最大的右子树。我们分别递归——在左子树DBGE中,由先序可得B为根节点,所以D为左子树,GE为右子树。当然,再往下一层D也不过是单点,所以可以直接输出了——最深最靠左的一个结点。GE的话在先序中我们D已经用过了,所以再往后看——是E,所以G为E的孩子,但是E出现在了这个子树的边界处,所以递归下去的只有G,输出,回溯,输出根节点E,再回溯,输出根节点B。这样以A为根节点的左子树就已经处理完了。右子树同理。所以——我们用一个递归就可以解决了。

下面就是代码啦~

#include<bits/stdc++.h>
using namespace std;
string s1, s2;
int now;
bool vis[30];//s1
map<char, int> m;
void find(int l, int r)
{
	if(l == r)//叶子节点
	{
		printf("%c", s2[l]);
		now++;//先序中直接下一位
		return;
	}
	int mid = s2.find(s1[now]);//start from 0
	now++;
	if(mid > l) find(l, mid - 1);//否则mid为边界点,当做根节点处理,不必再递归
	if(r > mid) find(mid + 1, r);
	printf("%c", s2[mid]);//输出这一子树的根
}

int main()
{
	while(cin >> s1 >> s2)
	{
		now = 0; 
		find(0, s1.size() - 1);
		puts("");
	}
	return 0;
}

迎评:)
——End——

  • 2
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值