剑指offer-面试题06-重建二叉树

package case06_ConstructBinaryTree;

public class ConstructBinaryTree {

	/**
	 * 输入某二叉树的前序遍历和中序遍历的结果,请重建出该二叉树。假设输入的前序遍历和中序遍历的结果中都不含有重复的数字。 例如:
	 * 输入的前序遍历序列{1,2,4,7,3,5,6,8} 输入的后序遍历序列{4,7,2,1,5,3,8,6} 重建出如下二叉树,并且输出其头结点。
	 *			 1
	 *		    / \ 
	 *		   2    3 
	 *        /    / \ 
	 *       4    5   6
	 *       \       /    
	 *        7     8
	 * 
	 * @param args
	 */
	public static void main(String[] args) {
		test1();
		System.out.println();
		test2();
		System.out.println();
		test3();
		System.out.println();
		test4();
		System.out.println();
		test5();
		System.out.println();
		test6();
		System.out.println();
		test7();
		System.out.println();
	}
	/**
	 * 
	 * @param preArr	前序遍历序列
	 * @param inArr		中序遍历序列
	 * @return 			重建二叉树的头结点
	 */
	public static BinaryTreeNode construct(int[] preArr, int[] inArr) {
		// 输入的合法性判断,两个数组都不能为空,并且都有数据,而且数据的数目相同
		if (preArr == null || inArr == null || preArr.length != inArr.length || preArr.length < 1)
			return null;
		return constructTree(preArr, 0, preArr.length - 1, inArr, 0, inArr.length - 1);
	}

    /**
     *
     * @param preArr 			前序遍历序列
     * @param pl        		前序遍历的开始位置
     * @param pr        		前序遍历的结束位置
     * @param inArr				中遍历序列
     * @param il		        中序遍历的开始位置
     * @param ir 		        中序遍历的结束位置
     * @return root				二叉树的根节点
     */
    public static BinaryTreeNode constructTree(int[] preArr, int pl, int pr,
                                               int[] inArr,int il, int ir) {

        BinaryTreeNode root = new BinaryTreeNode();
        // 开始位置大于结束位置说明已经没有需要处理的元素了
        if (pl > pr)
            return null;
        // 取前序遍历的第一个数字,就是当前的根结点
        root.data = preArr[pl];
        int index = il;
        while (index <= ir && inArr[index] != root.data) {
            index++;
        }
        if (index > ir)
            throw new RuntimeException("input invalid.");

        // 递归构建当前根结点的左子树,左子树的元素个数:index-il 个
        // 左子树对应的前序遍历的位置在[pl+1, pl+index-il]
        // 左子树对应的中序遍历的位置在[il, index-1]
        root.lchild = constructTree(preArr, pl + 1, index - il + pl, inArr, il, index - 1);;
        // 递归构建当前根结点的右子树,右子树的元素个数:ir-index个
        // 右子树对应的前序遍历的位置在[pl+index-il+1, pr]
        // 右子树对应的中序遍历的位置在[index+1, ir]
        root.rchild = constructTree(preArr, index - il + pl + 1, pr, inArr, index + 1, ir);

        return root;
    }
	
	//*****测试start*****//
	
	//中序遍历二叉树
	public static void printTree(BinaryTreeNode btn){
		if(btn != null){
			printTree(btn.lchild);
			System.out.print(btn.data + " ");
			printTree(btn.rchild);			
		}
	}
	
	// 普通二叉树  
    //              1  
    //           /     \  
    //          2       3  
    //         /       / \  
    //        4       5   6  
    //         \         /  
    //          7       8  
    private static void test1() {  
        int[] preArr = {1, 2, 4, 7, 3, 5, 6, 8};  
        int[] inArr = {4, 7, 2, 1, 5, 3, 8, 6};  
        BinaryTreeNode root = construct(preArr, inArr);  
        printTree(root);  
    }  
    // 所有结点都没有右子结点  
    //            1  
    //           /  
    //          2  
    //         /  
    //        3  
    //       /  
    //      4  
    //     /  
    //    5  
    private static void test2() {  
        int[] preArr = {1, 2, 3, 4, 5};  
        int[] inArr = {5, 4, 3, 2, 1};  
        BinaryTreeNode root = construct(preArr, inArr);  
        printTree(root);  
    }  
    
    // 所有结点都没有左子结点  
    //            1  
    //             \  
    //              2  
    //               \  
    //                3  
    //                 \  
    //                  4  
    //                   \  
    //                    5  
    private static void test3() {  
        int[] preArr = {1, 2, 3, 4, 5};  
        int[] inArr = {1, 2, 3, 4, 5};  
        BinaryTreeNode root = construct(preArr, inArr);  
        printTree(root);  
    }  
    
    // 树中只有一个结点  
    private static void test4() {  
        int[] preArr = {1};  
        int[] inArr = {1};  
        BinaryTreeNode root = construct(preArr, inArr);  
        printTree(root);  
    }  
  
    // 完全二叉树  
    //              1  
    //           /     \  
    //          2       3  
    //         / \     / \  
    //        4   5   6   7  
    private static void test5() {  
        int[] preArr = {1, 2, 4, 5, 3, 6, 7};  
        int[] inArr = {4, 2, 5, 1, 6, 3, 7};  
        BinaryTreeNode root = construct(preArr, inArr);  
        printTree(root);  
    }  
  
    // 输入空指针  
    private static void test6() {  
        construct(null, null);  
    }  
    
    // 输入的两个序列不匹配  
    private static void test7() {  
        int[] preorder = {1, 2, 4, 5, 3, 6, 7};  
        int[] inorder = {4, 2, 8, 1, 6, 3, 7};  
        BinaryTreeNode root = construct(preorder, inorder);  
        printTree(root);  
    }  
    
	//*****测试     end*****//
}


package case06_ConstructBinaryTree;

//构造二叉树节点
public class BinaryTreeNode {
	public int data;
	public BinaryTreeNode lchild;	//左子树节点
	public BinaryTreeNode rchild;	//右子树节点
	public BinaryTreeNode() {
	}
	public BinaryTreeNode(int data) {
		this.data = data;
	}
	
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值