二叉树的前序遍历123456 ,中序遍历321546 ,构建二叉树
从前序遍历知道根节点,从中序遍历划分左右子树,然后从前序遍历知道子树的根节点,从中序遍历知道子树的左右子树,以此类推,直到全部构建完。
/**
* 二叉树节点类
*/
public static class BinaryTreeNode {
int value;
BinaryTreeNode left;
BinaryTreeNode right;
}
/**
* 输入某二叉树的前序遍历和中序遍历的结果,请重建出该二节树。假设输入的前序遍历和中序遍历的结果中都不含重复的数字。
* @param preorder 前序遍历
* @param inorder 中序遍历
* @return 树的根结点
*/
public static BinaryTreeNode construct(int[] preorder, int[] inorder){
// 输入的合法性判断,两个数组都不能为空,并且都有数据,而且数据的数目相同
if (preorder == null || inorder == null
|| preorder.length != inorder.length
|| inorder.length < 1) return null;
return construct(preorder,0,preorder.length-1,inorder,0,inorder.length-1);
}
/**
* 这里不改变序列,而是改变开始位置与结束位置,可以理解为调整游标,从而达到改变序列的要求
* 实际就是改便了序列的有效位,根据序列的有效位,找出树的左子树与右子树有效位,递归构建树
* @param preorder 前序遍历序列
* @param ps 前序遍历序列的开始位置
* @param pe 前序遍历序列的结束位置
* @param inorder 中序遍历序列
* @param is 中序遍历序列的开始位置
* @param ie 中序遍历序列的结束位置
* @return 树的根结点
*/
public static BinaryTreeNode construct(int[] preorder, int ps, int pe, int[] inorder, int is, int ie){
// 开始大于位置结束位置,说明已经没有需要处理的元素了
if (ps > pe || is > ie){
return null;
}
// 取前序遍历的第一个数字,就是当前的根结点
int curRoot = preorder[ps];
int index = is;
// 在中序遍历的数组中找根结点的位置
while (index <= ie && inorder[index] != curRoot)
index++;
// 如果在整个中序遍历的数组中没有找到,说明输入的参数是不合法的,抛出异常
if (index > ie)
throw new RuntimeException("非法输入");
BinaryTreeNode node = new BinaryTreeNode();
node.value = curRoot;
// 构建当前根结点的左子树,左子树的元素个数:ps+1+index-is-1 - (ps+1) + 1 = index-is
// 左子树对应的前序遍历位置[ps+1,ps+1+index-is-1]
// 右子树对应的中序遍历位置[is,index-1]
node.left = construct(preorder,ps+1,ps+index-is,inorder,is,index-1);
// 构建当前根结点的右子树,右子树的元素个数ie-index
// 右子树对应的前序遍历的位置[ps+index-is+1,pe]
// 右子树对应的中序遍历的位置[index+1,ie]
node.right = construct(preorder,ps+1+index-is,pe,inorder,index+1,ie);
// 返回当前的根节点
return node;
}
二叉树的前序遍历,中序遍历,后序遍历,递归实现。
private static void preOrderTraverse(BinaryTreeNode treeNode){
if (treeNode == null)
return;
System.out.print(treeNode.value);
preOrderTraverse(treeNode.left);
preOrderTraverse(treeNode.right);
}
private static void inOrderTraverse(BinaryTreeNode treeNode){
if (treeNode == null)
return;
inOrderTraverse(treeNode.left);
System.out.print(treeNode.value);
inOrderTraverse(treeNode.right);
}
private static void postOrderTraverse(BinaryTreeNode treeNode){
if (treeNode == null)
return;
postOrderTraverse(treeNode.left);
postOrderTraverse(treeNode.right);
System.out.print(treeNode.value);
}
二叉树遍历的性质
已知前序遍历和中序遍历序列,可以唯一确定一棵二叉树。
已知后序遍历和中序遍历序列,可以唯一确定一棵二叉树。
需要注意的是,已知前序和后序遍历,是不能确定一棵二叉树的,
因为比如前序序列是ABC ,后序序列是CBA ,我们可以确定A 一定是根节点,但接下来哪个是左子树,哪个右子树,就不能唯一的确定了。