由前序和中序遍历重建二叉树

本文介绍了一种通过前序和中序遍历结果重建二叉树的方法。利用递归技术,文章详细阐述了如何确定根节点,并根据中序遍历找到左右子树,最终构建完整的二叉树结构。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

题目描述:输入某二叉树的前序遍历和中序遍历结果,请重建出该二叉树。假设输入的前序遍历和中序遍历的结果中都不包含重复的数字。例如输入前序遍历序列:{1,2,4,7,3,5,6,8}和中序遍历{4,7,2,1,5,3,8,6},则重建出图中所示二叉树并且输出它的头结点。

重建的二叉树:


思路:先找出根节点,然后利用递归方法构造二叉树

解法一:

package Problem6;
  3 /* 重建二叉树
  7  */
  8 //定义二叉树节点
  9 class BinaryTreeNode {
 10     public int value;
 11     public BinaryTreeNode leftNode;
 12     public BinaryTreeNode rightNode;
 14     // 无参构造函数
 15     public BinaryTreeNode() {}
 19     // 有参构造函数
 20     public BinaryTreeNode(int value) {
 21         this.value = value;
 22         this.leftNode = null;
 23         this.rightNode = null;
 24     }
 25 }
 27 public class ConstructBinaryTree {
 29     public static BinaryTreeNode construct(int preOrder[], int inOrder[],
 30             int length) throws Exception {
 31         if (preOrder == null || inOrder == null || length < 0) {
 32             return null;
 33         }
 34         return constructCore(preOrder, 0, preOrder.length - 1, inOrder, 0,
 35                 inOrder.length - 1);
 36     }
 38     public static BinaryTreeNode constructCore(int preOrder[],
 39             int startPreIndex, int endPreIndex, int inOrder[],
 40             int startInIndex, int endInIndex) throws InvalidPutException {
 41         // 头结点的值
 42         int rootValue = preOrder[startInIndex];
 44         // 构建一个只有一个根节点的二叉树
 45         BinaryTreeNode root = new BinaryTreeNode(rootValue);
 46         // 只有一个元素的情况下:
 47         if (startPreIndex == endPreIndex) {
 48             if (startInIndex == endInIndex
 49                     && preOrder[startInIndex] == inOrder[endInIndex]) {
 50                 System.out.println("只有一个元素");
 51                 return root;
 52             } else {
 53                 throw new InvalidPutException();
 54             }
 56         }
 57         // 最重要的一步:在中序遍历中找到根结点的索引
 58         int rootInIndex = startInIndex;
 59         while (rootInIndex <= endInIndex && inOrder[rootInIndex] != rootValue) {
 60             rootInIndex++;
 61         }
 62         if (rootInIndex == endInIndex && inOrder[rootInIndex] != rootInIndex) {
 63             throw new InvalidPutException();
 64         }
 65         // 根节点的左子树的长度
 66         int leftLength = rootInIndex - startInIndex;
 67         // 根节点的左子树的最右端的索引值
 68         int leftPreEndIndex = startPreIndex + leftLength;
 69         // 构建左子树
 70         if (leftLength > 0) {
 71             root.leftNode = constructCore(preOrder, startPreIndex + 1,
 72                     leftPreEndIndex, inOrder, startInIndex, rootInIndex - 1);
 73         }
 74         // 说明根节点存在右子树
 75         if (leftLength < endPreIndex - startPreIndex) {
 76             root.rightNode = constructCore(preOrder, leftPreEndIndex + 1,
 77                     endPreIndex, inOrder, rootInIndex + 1, endInIndex);
 78         }
 79         return root;
 80     }
 82     // 按照前序遍历打印二叉树的节点
 83     public static void printPreBinaryTree(BinaryTreeNode root) {
 84         if (root == null) {
 85             return;
 86         } else {
 87             System.out.println(root.value + " ");
 88         }
 89         if (root.leftNode != null) {
 90             printPreBinaryTree(root.leftNode);
 91         }
 92         if (root.rightNode != null) {
 93             printPreBinaryTree(root.rightNode);
 94         }
 95     }
 97     public static class InvalidPutException extends Exception {
 99         private static final long serialVersionUID = 1L;
100     }
102     /**
103      * @param args
104      * @throws Exception
105      */
106     public static void main(String[] args) throws Exception {
107         int preOrder[] = { 1, 2, 4, 7, 3, 5, 6, 8 };
108         int inOrder[] = { 4, 7, 2, 1, 5, 3, 8, 6 };
109         ConstructBinaryTree test = new ConstructBinaryTree();
110         printPreBinaryTree(test.construct(preOrder, inOrder, preOrder.length));
111     }
113 }

解法二:借助Arrays.copyOfRange( )实现递归调用

Arrays.copyOfRange(T[ ] original,int from,int to) --> 左闭右开

将一个原始的数组original,从下标from开始复制,复制到下标to,生成一个新的数组(包括下标from,不包括下标to

static class TreeNode {
     int val;
     TreeNode left;
     TreeNode right;
     TreeNode(int x) { val = x; }
 }
public TreeNode reConstructBinaryTree(int [] pre,int [] in) {
    if (pre == null || in == null) {
        return null;
    }
    if (pre.length == 0 || in.length == 0) {
        return null;
    }
    if (pre.length != in.length) {
        return null;
    }
    TreeNode root = new TreeNode(pre[0]);
    for (int i = 0; i < pre.length; i++) {
        if (pre[0] == in[i]) {
            root.left = reConstructBinaryTree(
                            Arrays.copyOfRange(pre,1,i+1),Arrays.copyOfRange(in,0,i));
            root.right = reConstructBinaryTree(
                            Arrays.copyOfRange(pre,i+1,pre.length),Arrays.copyOfRange(in,i+1,in.length));
        }
    }
    return root;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值