如何从数组表示构建不完整的二叉树

时间:2016-06-21 10:01:47

标签: data-structures binary-tree

如果输入是一个数组, var config = { apiKey: "", authDomain: "", databaseURL: "", storageBucket: "", } 表示没有节点。

输入:

null

请假设我已经检查了输入。

对于每个[1, 2, 3, null, 5, null, 7],其父级array[i]不会是array[i / 2](递归,因此root不能是null)。

如何构建具有这种逻辑关系的树:

null

每个节点应由 1 / \ 2 3 \ \ 5 7 对象表示:

TreeNode

我找到了blog here,其中构建了一个完整的树

但是如果树如上所述是不完整的,如何整齐有效地做到这一点?

测试数据:

[输入数组]

class TreeNode { public: int val; TreeNode *left; TreeNode *right; TreeNode(int x) : val(x), left(nullptr), right(nullptr) {} };

4 个答案:

答案 0 :(得分:1)

当将二叉树实现为数组时,它有助于实现 清楚地显示两个表示如何反映一个 另一个,并审查强调的数学结构 关系。

如果我们考虑0索引数组,则数学关系可以 被打破,

  • 根节点的索引为0

对于i:th节点(i是数组索引),我们有(验证)

  • 节点的左子节点具有索引2i + 1
  • 节点的右子节点具有索引2(i + 1)
  • 节点的父节点具有索引floor((i-1)/2)

所以,对于二叉树

Binary tree

如果我们让-表示null,则表示为

[0:a, 1:b, 2:c, 3:d, 4:e, 5:-, 6:-, 7:-, 8:-, 9:g, 10:-, 11:-, 12:-, 13:-, 14:-]

现在,要从数组创建OO表示,您只需应用这些索引规则。因此,既然您知道根节点是a,那么我们将其子节点放在:

  • 左:2*0 + 1 = 1 => b
  • 右:2*(0 + 1) = 2 => c

伪代码

for (int idx = 0; 2*(idx + 1) < len(arr); idx++) {
    if (arr[idx] == null) {
        // There is no node to add for this index
        continue;
    }

    TreeNode t = null;

    if (idx == 0) {
        // Root node case
        t = TreeNode(val: arr[idx]);
        binary_tree.add(id: idx, node: t);
    }

    // We do not know if these exist yet
    int left_idx = 2*idx + 1; 
    int right_idx = 2*(idx + 1);

    if (left_idx >= len(arr)) {
        // left_idx is out of bounds with respect to the array, 
        // and by extension so would the right node be
        continue;
    }

    TreeNode left = null;
    TreeNode right = null;

    if (arr[left_idx] != null) {
        // This node has never been encountered before
        // and it is non-null so it must be created.
        //
        // Since we know we have a root node then there is
        // no need to check if the tree already contains this
        // node, it simply is not possible. Ditto for the right
        // node.
        left = TreeNode(val: arr[left_idx]);
        binary_tree.add(id: left_idx, node: left);
    }

    if (right_idx >= len(arr)) {
        // There cannot be a right child
        continue;
    }

    if (arr[right_idx] != null) {
        // This node has never been encountered before
        // and it is non-null so it must be created.
        right = TreeNode(val: arr[right_idx]);
        binary_tree.add(id: right_idx, right);
    }

    // It does not matter if left or right is null
    t.set_left(left)
    t.set_right(right)    
}

答案 1 :(得分:0)

使用递归来使用数组的索引遍历节点,并使用Integer来允许null。

private TreeNode array2Tree(Integer[] data,TreeNode root, int index){

    if(index >= data.length){
      return root;
    }

    if(data[index] != null){
      TreeNode temp =  new TreeNode(data[index]);
      root = temp;
      root.left = array2Tree(data,root.left,2*index+1);
      root.right = array2Tree(data,root.right,2*index+2);
    }

    return root;
}

答案 2 :(得分:0)

我认为这个示例可以解释您的想法。

array : [5,4,8,11,null,17,4,7,null,null,null,5]
Tree : 

                      5
                     /  \
                    4    8
                   /    / \
                  11   17  4
                 /        /
                7        5

以上所有答案都是将输入数组视为一棵完整的树。所以left.child = 2 * idx + 1,right.child = 2 * idx + 2但实际上是错误的。 因为那些 [5,4,8,11,null,17,4,7,null,null,null,5] [5,4,8,11,null,17,4,7,null,null,null,null,null,5,null] 不一样

这是我的解决方法

public static TreeNode createTree(Integer[] array) {
        if (array == null || array.length==0) {
            return null;
        }

        Queue<TreeNode> treeNodeQueue = new LinkedList<>();
        Queue<Integer> integerQueue = new LinkedList<>();
        for (int i = 1; i < array.length; i++) {
            integerQueue.offer(array[i]);
        }

        TreeNode treeNode = new TreeNode(array[0]);
        treeNodeQueue.offer(treeNode);

        while (!integerQueue.isEmpty()){
            Integer leftVal = integerQueue.isEmpty() ? null : integerQueue.poll();
            Integer rightVal = integerQueue.isEmpty() ? null : integerQueue.poll();
            TreeNode current = treeNodeQueue.poll();
            if (leftVal !=null) {
                    TreeNode left = new TreeNode(leftVal);
                    current.left = left;
                    treeNodeQueue.offer(left);
            }
            if (rightVal !=null){
                    TreeNode right = new TreeNode(rightVal);
                    current.right = right;
                    treeNodeQueue.offer(right);
            }
        }
        return treeNode;
    }

答案 3 :(得分:0)

在 Java 中:

public class TreeNode {
    public int val;
    public TreeNode left;
    public TreeNode right;
    public TreeNode() {}
    public TreeNode(int val) { this.val = val; }
    public TreeNode(int val, TreeNode left, TreeNode right) {
        this.val = val;
        this.left = left;
        this.right = right;
    }

    /**
     * Create a tree from array using levels i.e {-2,3,4,null,null,5,null,null,null,null,null, 6 } becomes 2 le-> 3, 2 re->4, 4 le->5, 5 le->6
     * @param arr the arr to be converted to a tree
     * @return
     */
    public static TreeNode createTreeFromArray(Integer[] arr){
        TreeNode root = new TreeNode();
        return  insertLevelOrder(arr, root, 0);
    }


    static TreeNode insertLevelOrder(Integer[] arr, TreeNode root,
                                 int i)
    {

        // Base case for recursion
        if (i < arr.length) {
            if(arr[i] == null)
                return null;
            TreeNode temp = new TreeNode(arr[i]);
            root = temp;

            // insert left child
            root.left = insertLevelOrder(arr, root.left,
                     2* i + 1);

            // insert right child
            root.right = insertLevelOrder(arr, root.right,
                     2* i + 2);
        }
        return root;
    }
}