【问题标题】:reconstruct binary search tree from a flatten list in Java?从Java中的扁平列表构造二叉搜索树?
【发布时间】:2014-01-14 20:01:54
【问题描述】:

我有这段代码,用于从预排序遍历元素的扁平列表中重建二叉搜索树。

我看到此代码有效,但无法理解如何。代码如下:

public static Node reconstructfromflattenBST(List<Integer> list){
        if (list.isEmpty()){
            return null;
        }
        int data = list.remove(0);
        Node root = new Node(data);
        root.left=reconstructfromflattenBST(list);
        root.right=reconstructfromflattenBST(list);

        return root;



    }

根据我对这种方法的理解,不会创建正确的树。因为当控件到达root.right 时,list 为空。但这种方法显然有效。

我提供了 [5 3 1 4 8 6 9] 的预购输入。树构建完成后,我对构建的树进行了前序遍历,它给出了与输入列表相同的元素顺序。

编辑: 这是我的展平子程序:

public static List<Integer> flattenBinaryTree(Node root, List<Integer> list){

        if (list==null){
            list=new ArrayList<Integer>();
        }
        if (root==null){
            return list;
        }
        list.add(root.data);
        List<Integer> list1 = flattenBinaryTree(root.left,list);
        return flattenBinaryTree(root.right, list1);
    }

【问题讨论】:

    标签: java binary-tree binary-search-tree preorder


    【解决方案1】:

    你是对的。如果在展平树时也写出了空节点,可能是空整数,那么:

        Integer data = list.remove(0);
        if (data == null) {
            return null;
        }
        Node root = new Node(data.intValue());
    

    将重建完全相同的树。 即:扁平化添加停止的空叶子。

    List<Integer> list = new LinkedList<>();
    flatten(list, tree);
    
    void flatten(List<Integer> list, Node tree) {
        if (tree == null) {
            list.add(null);
            return;
        }
        list.add(tree.data);
        flatten(tree.left);
        flatten(tree.right);
    }
    

    或者使用有序树:

    public static Node reconstructfromflattenBST(List<Integer> list){
        reconstruct(list, Integer.MAX_VALUE, true);
    }
    
    public static Node reconstruct(List<Integer> list, int priorData, boolean left){
        if (list.isEmpty()){
            return null;
        }
        int data = list.remove(0);
        if ((data <= priorData) != left) {
            return null;
        }
        Node root = new Node(data);
        root.left=reconstruct(list, data, true);
        root.right=reconstruct(list, data, false);
    
        return root;
    }
    

    【讨论】:

    • 我认为 right subtree 永远不会被构造,因为列表在分配 it reaches that line of code where root.right 之前被清空
    • 正如您在我的代码上方看到的,我没有进行data==null 检查,它是如何工作的?
    • 我已经包含了我的展平子程序,它适用于它。
    • 你得到一棵树,其中只有左分支被填充。
    • 正是..但是当我进行预购遍历时,它会正确打印输入列表,这是怎么回事?
    【解决方案2】:

    根据我对这种方法的理解,不会创建正确的树。因为当控件到达root.right时,list为空。

    没错。

    但这种方法显然有效。

    我提供了 [5 3 1 4 8 6 9] 的预购输入。树构建完成后,我对构建的树进行了前序遍历,它给出了与输入列表相同的元素顺序。

    这个观察与右子树总是空的并不矛盾。

    更好的单元测试会构建一棵树,将其展平,重建它,并比较重建后的树与原始树的形状相同。这样的测试会失败。事实上,从节点的预排序列表中忠实地重建树是不可能的,因为不同的树具有相同的预排序列表。例如,两者

    1              1
     \            / \
      2          2   3
       \
        3
    

    有预购清单 1 2 3.

    【讨论】:

    • 左边的不是 BST。这里的想法是树结构持久化到数组中并重建同一棵树。预购数组是最好的,因为可以从它而不是从其他任何东西重建 BST。
    • 对,如果数字不同,则 BST 由其预排序列表标识,但您重建的树不是 BST。
    • 我猜你是对的。上面的重构并没有返回一个有效的 BST。
    【解决方案3】:

    我认为问题在于写出树的预排序值并不能保证树最初是 BST,因此初始函数的输出应该是一根从左侧向下移动的棒,以 5 为根。

          5
         3
        1
       4
      8
     6
    9
    

    这棵树的前序遍历为 [5, 3, 1, 4, 8, 6, 9],但它不是 BST,因此不是树的正确表示。 Joop Eggen 出现了正确的版本

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2016-03-02
      • 1970-01-01
      • 2023-03-17
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多