【历年真题】严格二叉树已知前序和后序还原这棵树
一颗二叉树,其左右子树都空,或都不空,则为“严格二叉树”,用先序遍历
和后序遍历能确定一颗严格二叉树,二叉树的前序序列为 ABDECFHIGJLKMN,后序序列为 DEBHIFLJMNKGCA.
然后输出其中序遍历
【题解】
主要就是根据这个二叉树的特点写个递归就好。 因为如果有左子树一定有右子树。 所以先序遍历当前节点的下一个节点一定是左子树的根节点。 那么我们只要在后序遍历中找到这个左子树的根节点就好了。 然后,在后序遍历中这个左子树的根节点的左边的点肯定就都是它的子树里的节点了。 那么它后面的点是什么呢?肯定就是当前节点的右子树的后序遍历了(除了最后一个节点即根节点本身外) 然后递归,找到每个节点的左右儿子节点就行【代码】
#include <cstdio>
#include <iostream>
using namespace std;
const int N = 100;
int l[N+10],r[N+10],root,cur;
char dic[N+10];
//前序后序
string s1,s2;
int len1,len2;
//返回和前序中l1..r1后序中l2..r2对应的树的根节点
int doit(int l1,int r1,int l2,int r2){
if (l1>r1) return -1;
char key = s1[l1];
int now = ++cur;
dic[now] = key;
if (l1+1>r1) return now;//如果是叶子节点,就直接返回这个节点
//不是叶子节点,那么一定有左子树和右子树
char keyl = s1[l1+1];
int j;
for (int i = l2;i <= r2;i++)//在后序中找到key的左子树的根节点
if (s2[i]==keyl){
j = i;
break;
}
//则l2..j这一段是key的左子树对应的后序遍历
int len = j-l2+1;
l[now] = doit(l1+1,l1+1+len-1,l2,j);
//而j+1..r2-1这一段是key的右子树对应的后序遍历
r[now] = doit(l1+1+len,r1,j+1,r2-1);
return now;
}
void dfs(int x){
if (x<=0) return;
dfs(l[x]);
printf("%c",dic[x]);
dfs(r[x]);
}
int main(){
//freopen("D:\\rush.txt","r",stdin);
cin >> s1 >> s2;
len1 = s1.size();len2 = s2.size();
root = doit(0,len1-1,0,len2-1);
dfs(root);//输出其中序遍历
return 0;
}