输入:
ABC
BAC
输出:
BCA
ABC
输入:
FDXEAG
XDEFAG
输出:
XEDGAF
FDAXEG
思路:
目标:
1.找节点 。
2.找左右子树。
前序遍历字符串能明确知道第一个是节点,也明确知道随后跟着的是左子树字符串+右子树字符串。但是不知道左子树长度,右子树的长度。因此下步目标就是找左子树的长度和右子树长度。
中序遍历中,节点在中间,左边是左子树的中序遍历,右边就是右子树的中序遍历。
知道根节点下标,就可以得出左右子树的中序遍历字符串zstr,ystr。也知道前序遍历左子树的长度zstr.length和右子树的长度ystr.length。
中序遍历构成,zstr.length+根节点+ystr.length 。
前序遍历构成,根节点+zstr.length+ystr.length 。
代码实现:
#include<bits/stdc++.h>
using namespace std ;
string str1 ;
string str2 ;
struct tree{
char value ;
tree *left ;
tree *right ;
};
//根据前中序建树
tree *build(int st1 , int end1 , int st2 , int end2){
//初始化当前节点
tree *root = new tree ;
root->left = nullptr ;
root->right = nullptr ;
root->value = str1[st1] ;//当前树的节点,即前序遍历的第一个。当前节点初始化完毕
char p = str1[st1] ;
int index = 0 ;
//index是中序遍历节点坐标。(index-st2)是左子树的长度
//左子树前序遍历下标范围st1+1,st1+(index-st2);左子树中序遍历下标范围st2,index-1
//右子树前序遍历下标范围(st1+(index-st2))+1,end1;右子树中序遍历下标范围index+1,end2
for( int i = 0 ; i <= end2 ; i++){
if(p == str2[i]){
index = i ;
break ;
}
}
//在中间就有左右子树,在开头没有左子树,在结尾没有右子树。
//如果index不是在开头,就证明还有左子树
if( st2 != index )
root->left = build(st1+1,st1+index-st2,st2,index-1);
//如果index不是在结尾,就证明有右子树。
if( end2 != index )
root->right = build(st1+index-st2+1,end1,index+1,end2);
return root ;
}
//打印后序遍历
void prt(tree *root){
if(root->left != nullptr)
prt(root->left);
if(root->right != nullptr)
prt(root->right);
printf("%c",root->value) ;
}
//打印层序遍历
void print_tree(tree *root){
queue<tree*> q ;
q.push(root) ;
while(!q.empty()){
tree *tr = q.front() ;
q.pop() ;
cout<<tr->value ;
if( tr->left != nullptr)
q.push(tr->left) ;
if( tr->right != nullptr)
q.push(tr->right) ;
}
}
int main(){
cin>>str1 ;
cin>>str2 ;
tree *root = build(0,str1.length()-1,0,str1.length()-1) ;
prt(root);
cout<<endl ;
print_tree(root);
}