思路
首先,根据题设,我们可以得到这样的信息:
- 根节点:先序遍历的第一个值即为根节点;
- 中序遍历一定是:中序遍历一定是 { 根节点的左子树中的节点集合 },root,{ 根节点的右子树中的节点集合 }。
假设PreOrder: GDAFEMHZ,InOrder: ADEFGHMZ
解决问题的思路如下:
- 找到根节点,根据前序遍历,可以得到根节点;
- 剩下的节点必然在root的左或右子树中的节点;
- 观察中序遍历。其中root节点左侧的必然是root的左子树中的节点,G右侧的必然是root的右子树中的节点,root不在中序遍历的末尾或开始就说明根节点的两颗子树都不为空;
- 观察根节点的左子树ADEF,按照前序遍历的顺序来排序为DAFE,因此左子树的根节点为D,并且A是左子树的左子树中的节点,EF是左子树的右子树中的节点;
- 同样的道理,观察右子树节点HMZ,前序为MHZ,因此右子树的根节点为M,左子节点H,右子节点Z。
上面的过程是递归的。先找到当前树的根节点,然后划分为左子树,右子树,然后进入左子树重复上面的过程,然后进入右子树重复上面的过程。最后就可以还原一棵树了。
Java语言实现
package newCode;
import adt.TreeNode;
public class BuildTree {
public TreeNode reBuildTree(int[] pre, int[] in) {
if (pre == null || in == null || pre.length != in.length) {
return null;
} else {
return reBuild(pre, 0, pre.length - 1, in, 0, in.length - 1);
}
}
private TreeNode reBuild(int[] pre, int startPre, int endPre, int[] in, int startIn, int endIn) {
if (startPre > endPre || startIn > endIn)//先对传的参数进行检查判断
return null;
int root = pre[startPre];//数组起始位置是树的根节点
int rootLocate = locate(root, in, startIn, endIn);//对根节点进行定位
if (rootLocate == -1) //没有在中序遍历中找到根节点
return null;
TreeNode rootNode=new TreeNode(root);
rootNode.setLeft(reBuild(pre, startPre+1, startPre+rootLocate-startIn, in, startIn+1, rootLocate-1));//递归构建左子树
rootNode.setRight(reBuild(pre, startPre+rootLocate-startIn+1, endPre, in, rootLocate+1, endIn));//递归构建右子树
return rootNode;
}
//对根节点进行定位,找中序遍历中根节点的位置
private int locate(int root, int[] in, int startIn, int endIn) {
for (int i = startIn; i < endIn; i++)
{
if(root == in[i])
return i;
}
return -1;
}
}
以上。。。