信息学奥赛一本通 二叉树遍历

题目是:

【题目描述】

输入一棵二叉树的先序和中序遍历序列,输出其后序遍历序列。

【输入】

共两行,第一行一个字符串,表示树的先序遍历,第二行一个字符串,表示树的中序遍历。树的结点一律用小写字母表示。

【输出】

一行,表示树的后序遍历序列。

【输入样例】

abdec
dbeac

【输出样例】

debca

额,真丢脸啊,这道题从11月7日卡在脑袋里卡到了现在(mmp硬是没有看题解);

不过老李讲的还是挺好的,打call;

本题利用了先序遍历的“先根”性质(每输出的一个值都是当先dfs时间戳的节点的值),且序列中的第一个元素一定是根节点;——性质1;

中序遍历则利用了“左左右右”(左边的是左儿子,右边是右儿子);——性质2;

两者相结合:

我们就可以用先序遍历的根节点,去找这个根节点在中序遍历的位置,那么利用性质2,去找它的左儿子和右儿子的区间分别在哪里,确定了左儿子和右儿子的区间后,这两个区间内一定又会有一个“当爸爸的父亲节点“,而这个区间里面的父亲节点,一定是先序遍历中当前节点向后的一个节点(性质1)相当于二分;

下面是代码(st是start的缩写,en是end的缩写)

1、数组(在遍历的时候就输出)

#include<bits/stdc++.h>
using namespace std;
string s1,s2;
void wans( int st1 , int en1 , int st2 , int en2 ){
	if( st1 <= en1 ){
		int root = s2.find ( s1[st1] , st2 );
		wans ( st1+1 , st1+root-st2 , st2 , root-1 );
		wans ( st1+root-st2+1 , en1 , root+1 , en2 );
		cout<<s1[st1];
	}
}
int main(){
	cin>>s1;
	cin>>s2;
	wans(0 , s1.size()-1 , 0 , s2.size()-1 );
	return 0;
}
2、建树,先建树后常规跑后序 dfs;

#include<bits/stdc++.h>
using namespace std;
typedef struct node;
typedef node *tree;
struct node{
	char data;
	tree l,r;
};
tree root;
string s1,s2;
void build( int st1 , int en1 , int st2 , int en2 , tree &bt ){
	bt=new node;
	bt->data = s1[st1];
	if( st1 <= en1 ){
		int x = s2.find( s1[st1] , st2 );
		build( st1+1 , st1+x-st2 , st2 , x-1 , bt->l);
		build( st1+x-st2+1 , en1 , x+1 , en2 , bt->r);
	}
	else
	    bt = NULL;
}
void visit( tree bt ){
	if( bt ){
		visit( bt->l );
		visit( bt->r );
		cout<<bt -> data;
	}
}
int main(){
	cin>>s1;
	cin>>s2;
	build( 0 , s1.size()-1 , 0 , s2.size()-1 , root );
	visit(root);
	return 0;
}
感觉lqx和hy同学学得很快,加油!
  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值