时间限制 : - MS; 空间限制 : 65536 KB;评测说明 : 1s;
两行,两个字符串分别表示前序和中序遍历的序列
一行,一个字符串,表示后序遍历的序列
ABGKLMCHJF
BLKMGAHCJF
LMKGBHFJCA
一道基础的树类型的应用,简单来说就是知道前序,中序求后序,后面会补充知道后序,中序求前序。
因为前序的排列方式是:根,左,右;中序排列方式:左,根,右;将前序存放在string a中,中序存放在string b中,我们可以得知:root=a[0];此时中序就被分成了左右子树两个部分,接着再寻找左子树的root和右子树的root。因qi先从左子树找起,找完左子树找右子树。最后输出后序。
例:如果a=“ABC”,b="BAC",则root='A',此时b分成了‘BA’和‘AC’两个部分。因为A中B是A后的第一个字符,所以B是A的左子树。此时,b中只剩下了C。因C在A右边,所以C就是A的右子树。
那么解法就很明显了,通过前序和中序得到树的形状,再求出后序。
代码如下(恩····有误····但不知道错在哪里系列,希望有大佬能帮忙改改····)
#include
#include
#include
using namespace std;
char a[1005],b[1005];
int t,tree[28][4],yes,maxn;
bool s[28];
void print(int x)
{
if (0maxn)
maxn=qt;
s[a[i]-'A'+1]=1;
yes=0;
if (pan(a[gen],a[i]))
tree[a[gen]-'A'+1][3]=qt;
else
tree[a[gen]-'A'+1][2]=qt;
tree[qt][1]=a[gen]-'A'+1;
if (yes==0)
gen=i;
}
return ;
}
int main()
{
// freopen("ceshi.in","r",stdin);
int i;
cin>>a;
scanf("\n");
cin>>b;
t=strlen(a);
s[a[0]-'A'+1]=1;
for (i=0;i<=t-1;i++)
if (b[i]==a[0])
{
check(0,i);//建左子树 ;
break;
}
check(i,t-1);//建右子树;
print(a[0]-'A'+1);
return 0;
}
不得不说这段代码特别长(确实emmm),还是错的(是我自己的问题吧····)所以有没有更简单的方法呢?答案就是省略掉中间建树的过程,直接输出后序,这里我们运用到了递归(递归蒟蒻不想说话····)。先放代码再进行解释(恩,能AC)
#include
using namespace std;
const int maxn = 10000 + 5;
char s1[maxn], s2[maxn];
int a, b, ans;
void build(int n, char *str1, char *str2) {
if(n <= 0) return;
int s = strchr(str2, str1[0]) - str2;
build(s, str1 + 1, str2);
build(n - 1 - s, str1 + s + 1, s + str2 + 1);
cout << str1[0];
}
int main() {
cin >> s1 >> s2;
int len = strlen(s1);
build(len, s1, s2);
cout << endl;
return 0;
}
解析:
用s1存前序,s2存中序,因为s1和s2的长度是一模一样的,所以我们只需要测量s1的长度即可。主函数大概就分为:输入——测长——输出即可,关键部分在于build函数。
首先先看参数部分,n代表的是当前的根节点(root),*str1是一个指针函数,str1中特定长度的字符,*str2同理(不太清楚的朋友,可以先去了解一下指针)。
第一步:当n==0时返回,此时代表已经找到了左儿子或者右儿子。
当不满足第一步,执行第二步:在str2中查找str1的第一个字符的位置,并存在s中(注:返回的是一个地址,减去str2代表返回字符所在的位置)。然后,递归函数——>寻找左子树——>寻找游子树。//这一步过程实际上就是在隐形建树,但不保存。
第三步:输str1当前的第一个字符。//后面三项操作,实际上就是正常对树输出后序的操作,如果要输出中序,或者前序,改动str1的位置就能实现。(或者也可以说,因为实在两个递归函数之后,所以是输出后序emmmm...)
文字说明可能不是很清晰,接下来我们就距离说明一下(不会插入图片的我大概只能用文字了qwq,见谅):
int main:已知前序:ABDEC,中序:DBEAC,测得长度len=5;开始进行函数;
build(1(root)):(前提:n=5,str1=“ABDEC”,str2=“DBEAC”)因n>0,查找str1[0](A),得到s=3;进入递归1;
build(1(left)):(前提:n=3,str1="BDEC",str2="DBEAC")因为n>0,查找str1[0](B),得到s=1;进入递归1;
重复上述操作,直到n=0时(也就是查找到D时)
build(2(left)):(前提:n=0,str1='EC',str2='DBEAC')因n=0,return;返回到:(n=1,str1=‘DEC’,str2='DBEAC')的位置,进入递归2;
build(2(right)):(前提:n=1-0-1=0,str1='DEC'+0+1='EC',str2='DBEAC'+0+1='BEAC')因n=0,return;返回(n=1,str1=‘DEC’,str2=‘DBEAC’),输出。
重复上述操作(大概过程就是这样啦)
总结:
每次写代码都是一种我的代码是如此的优美,然后本地AC提交WA,好不容易做出一道题被别人说是水题qwq。自己的递归这一块还是比较欠缺,看来还是需要多刷题啊emmmmm。但也有代码功底不强的情况,平常写的博客太少了所以经验欠缺(是这样吗????)。