剑指offer重构二叉树超详细讲解
题目:输入某二叉树的前序遍历和中序遍历的结果,请重构该二叉树,假设输入的前序遍历和中序遍历的结果不含重复的数字。例如
前序遍历{1,2,4,7,3,5,6,8}
中序遍历{4,7,2,1,5,3,8,6}
显然此二叉树应该为
/// 1
/// / \
/// 2 3
/// / / \
/// 4 5 6
/// \ /
/// 7 8
前序遍历序列的第一个数字1就是根节点。扫描中序遍历,就能确定根节点的位置。
根据中序遍历的特点:
在根节点前面的数字4 7 2都是左子树节点的值
在根节点1后面的数字5 3 8 6都是右子树的值
我们可以用递归的方法去完成重构二叉树
我们先根据前序遍历的第一个数字创建根节点,接下里在中序遍历序列找到根节点位置,这样能确定左右子树节点数量。这样就能递归调用分别取构建他们的左右子树。
过程如下:
-
Pre 1 2 4 7 3 5 6 8
Ord 4 7 2 1 5 3 8 6
将根节点1分成 左树4 7 2 和 右数 5 3 8 6 -
构建1的左子树
Pre 2 4 7
Ord 4 7 2
构建2的左子树
Pre 4 7
Ord 4 7
构建4的右子树
Pre 7
Ord 7
根节点4右树构建完成
中序遍历结果 4 7
根节点2左树构建完成
中序遍历结果 4 7 2
根节点1左树构建完成 -
构建1的右子树
Pre 3 5 6 8
Ord 5 3 8 6
构建3的左子树
Pre 5
Ord 5
3节点左树完成
中序遍历结果 5 3
构建3的右子树
Pre 6 8
Ord 8 6
构建6的左子树
Pre 8
Ord 8
根节点6左树构建完成
中序遍历结果 8 6
根节点3右树构建完成
中序遍历结果 5 3 8 6
根节点1右树构建完成
中序遍历结果 4 7 2 1 5 3 8 6
树已创造完成。下面上代码:
#include<bits/stdc++.h>
using namespace std;
struct BTNode{
int value;
BTNode* left;
BTNode* right;
};
void print(BTNode* head)
{
if(head==NULL)return;
print(head->left);
cout<<head->value<<" ";
print(head->right);
}
BTNode* ConstructCore
(int* startPre,int* endPre,int* startOrd,int* endOrd)
{
cout<<" 开始 前序遍历区间"<<*startPre<<"->"<<*endPre<<" || 中序遍历区间"<<*startOrd<<"->"<<*endOrd<<endl;
//前序遍历的第一个数字就是根节点
int rootvalue=startPre[0];
BTNode* root=new BTNode();
root->value=rootvalue;
root->left=root->right=NULL;
//如果只有一个节点就返回
if(startPre==endPre)
{
return root;
}
//中序遍历找到根节点的位置,其左为左子树,右为右子树
int* rootoder=startOrd;
while(rootoder<=endOrd&&*rootoder!=rootvalue)
rootoder++;
int leftLenth=rootoder-startOrd;//左子树总长度
int* leftPreend=startPre+leftLenth;//左子树末尾
if(leftLenth>0)
{
cout<<"构建左子树:";
root->left= ConstructCore(startPre+1,leftPreend,startOrd,rootoder-1);
}
if(leftLenth<endPre-startPre)
{
cout<<"构建右子树:";
root->right=ConstructCore(leftPreend+1,endPre,rootoder+1,endOrd);
}
cout<<"中序遍历root:";
print(root);
cout<<endl;
return root;
}
BTNode* Construct(int* preoder,int* inorder,int lenth)
{
cout<<"重建二叉树:";
return ConstructCore(preoder,preoder+lenth-1,inorder,inorder-1+lenth);
}
int main()
{
int pre[8]={1,2,4,7,3,5,6,8};
int ord[8]={4,7,2,1,5,3,8,6};
cout<<"前序遍历为:1 2 4 7 3 5 6 8"<<endl;
cout<<"中序遍历为:4 7 2 1 5 3 8 6"<<endl;
BTNode* head=Construct(pre,ord,8);
return 0;
}
代码运行结果: