二叉树——中序、后序建树,前序输出

142 篇文章 0 订阅
73 篇文章 0 订阅

原题 https://www.luogu.org/problemnew/show/P1030
题解
中序、后序,中序、前序均可唯一确定一颗棵二叉树。
指针解法:

#include<bits/stdc++.h>
using namespace std;
struct tree{
	char data;
	tree* left;
	tree* right;
};
inline int find(char* begin,char c){
	char*p;
	int i=0;
	for(p=begin;1;p++){//直接用地址进行操作 
		if(*p==c) return i;
		i++;
	}
}
//ldr是中序,lrd是后序 
tree* create(char* ldr,char* lrd,int len){//len是后序序列中根节点的位置 
	if(len<=0) return NULL;//设置返回条件 
	tree* p=new tree;//用指针操作 ,先建立节点 
	p->data=lrd[len-1];//从后序序列取出最后一个作为根节点的值 
	int i=find(ldr,p->data);//在中序序列中找到根,分出左右子树 
	p->left=create(ldr,lrd,i);//i是左子树中根节点在后序序列中的位置 
	p->right=create(ldr+i+1,lrd+i,len-1);//len-1是右子树的根节点在后序序列中的位置 
	return p;//返回地址 
}
void dlr(tree* t){//先序遍历 
	cout<<t->data;//根 
	tree* p;
	if(p=t->left) dlr(p);//左 
	if(p=t->right) dlr(p);//右 
}
int main()
{
	char a[10],b[10];
	cin>>a;cin>>b;
	tree* t=create(a,b,strlen(a));//设置成指针变量 
	dlr(t);//传的是地址 
	return 0;
}

在这里插入图片描述
静态数组解法:
写法一:


#include<bits/stdc++.h>
using namespace std;
char s1[15],s2[15];//s1是中序序列,s2是后序序列 
//不建树,直接输出;(建树时的节点顺序就是先序遍历的顺序,可以省略) 
void dfs(int l1,int r1,int l2,int r2){
	if(l1>r1) return;//中序遍历 
	//当l1=r1时,序列只有一个元素,即叶节点 
	int p;
    for(int i=l1;i<=r1;i++){
    	if(s1[i]==s2[r2]){//s2[r2]是根节点 
    		p=i;
			break;//剪枝 
		}
	}
	cout<<s1[p];
	int d1=(p-1)-l1;//在s1中计算左子树的长度 
	int d2=(r1-1)-p;//在s2中计算右子树的长度 
	dfs(l1,p-1,l2,l2+d1);
	dfs(p+1,r1,(r2-1)-d2,r2-1);
}
int main()
{
	int len;
	cin>>s1>>s2;
	len=strlen(s1);//s1是中序序列,s2是后序序列 
    dfs(0,len-1,0,len-1);//下标从零开始
	return 0; 
}

在这里插入图片描述
写法二:

#include<bits/stdc++.h>
using namespace std;
string a,b;//实质是字符串数组 ,a是中序序列,b是后序序列 
int dfs(int left1,int right1,int left2,int right2)
{
	int m=a.find(b[right2]);
	cout<<b[right2];
	//若m==left1,说明这个序列只有一个元素,即叶节点 
	int d1=m-1-left1;//在中序序列中求左子树长度 
	int d2=right1-(m+1);//在中序序列中求右子树长度
	if(m>left1) dfs(left1,m-1,left2,left2+d1);
	if(m<right1) dfs(m+1,right1,right2-1-d2,right2-1);
	//以上是长度的一种算法,另一种算法更好理解
	/*
	right2-1-d2=left2+(m-left1);
	m-left1是中序序列中左子树的长度,也是后序序列中左子树的长度 
	left2+(m-left1) 就是后序序列右子树第一个元素的坐标 
	同理,left2+d1=left2+(m-1-left1) 
	*/ 
}
int main()
{
	cin>>a>>b;//string.size()是长度,要转化为下标 
	dfs(0,a.size()-1,0,b.size()-1);
	return 0;
}

在这里插入图片描述

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值