【题目描述】
树的凹入表示法主要用于树的屏幕或打印输出,其表示的基本思想是兄弟间等长,一个结点的长度要不小于其子结点的长度。二叉树也可以这样表示,假设叶结点的长度为1,一个非叶结点的长度等于它的左右子树的长度之和。
一棵二叉树的一个结点用一个字母表示(无重复),输出时从根结点开始:
每行输出若干个结点字符(相同字符的个数等于该结点长度),如果该结点有左子树就递归输出左子树;如果该结点有右子树就递归输出右子树。
假定一棵二叉树一个结点用一个字符描述,现在给出先序和中序遍历的字符串,用树的凹入表示法输出该二叉树。
【输入】
两行,每行是由字母组成的字符串(一行的每个字符都是唯一的),分别表示二叉树的先序遍历和中序遍历的序列。
【输出】
行数等于该树的结点数,每行的字母相同。
【输入样例】
ABCDEFG
CBDAFEG
【输出样例】
AAAA
BB
C
D
EE
F
G
————————————————
思路:按先序遍历顺序找,则找的结点和b中的每个字符是一一对应的关系,在中序遍历查找这个字符,则它就是根,它在b的左部分即为左子树,右边则为右子数部分。
#include<iostream>
#include<cstdio>
#include<cstring>
#define N 100001
using namespace std;
char a[N],b[N];
int c[N],lena,lenb;
int f(int l1,int r1,int l2,int r2)
{
if(l1 == r1)//叶子结点长度为1
{
c[l1] = 1;
return c[l1];
}
int i;
for(i = l2;i <= r2;i++)
if(a[l1] == b[i])
break;
if(i < r2)
c[l1] += f(r1-(r2-(i+1)),r1,i+1,r2);//递归求出右儿子长度
if(i > l2)
c[l1] += f(l1+1,l1+i-l2,l2,i-1);//递归求出左儿子长度
return c[l1];
}
int main()
{
cin >> a >> b;//a先序和b中序
lena = strlen(a);
lenb = strlen(b);
f(0,lena-1,0,lenb-1);
for(int i = 0;i < lena;i++)
{
for(int j = 1;j <= c[i];j++)
cout << a[i];//先序遍历顺序输出
cout << endl;
}
}
程序二
#include<cstdio>
#include<iostream>
#include<cstring>
using namespace std;
int i = -1,a[200];
string s1,s2;
int tree(int l,int r)
{
int tot = 0,k = ++i; //a[i]表示结点i的长度
int m = s2.find(s1[k]);//中序遍历中查找这个字符,它就是根他在s2的左边部分就是左子树 右边是右子树
if(m > l) tot += tree(l,m-1);//递归求左子树长度
if(m < r) tot += tree(m+1,r);//递归求右子树长度,再推出根的长度
if(l == r) tot = 1;//叶子结点长度为1
a[s1[k]] = tot;//记录答案
return tot;
}
int main(){
cin >> s1 ;
cin >> s2;
tree(0,s1.size()-1);//两个字符串长度一样取一个就可以了
for(int i = 0 ; i < s1.size();i++)
{
for(int j = 1; j <= a[s1[i]];++j)
putchar(s1[i]);//先序遍历输出即可
putchar('\n');
}
return 0;
}