【问题标题】:How to build an incomplete binary tree from array representation如何从数组表示中构建不完整的二叉树
【发布时间】:2016-06-21 10:01:46
【问题描述】:

如果输入是一个数组,其中null 表示没有节点。

输入:

[1, 2, 3, null, 5, null, 7]

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

对于每个array[i],其父array[i / 2]不会是null(递归,所以root不能是null)。

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

   1
 /    \
2      3
 \      \ 
  5      7

每个节点应该由一个TreeNode 对象表示:

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

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

但是如果上面提到的树是不完整的,如何整齐高效地做呢?

测试数据:

[输入数组]

[-64,12,18,-4,-53,null,76,null,-51,null,null,-93,3,null,-31,47,null,3,53,-81,33,4,null,-51,-44,-60,11,null,null,null,null,78,null,-35,-64,26,-81,-31,27,60,74,null,null,8,-38,47,12,-24,null,-59,-49,-11,-51,67,null,null,null,null,null,null,null,-67,null,-37,-19,10,-55,72,null,null,null,-70,17,-4,null,null,null,null,null,null,null,3,80,44,-88,-91,null,48,-90,-30,null,null,90,-34,37,null,null,73,-38,-31,-85,-31,-96,null,null,-18,67,34,72,null,-17,-77,null,56,-65,-88,-53,null,null,null,-33,86,null,81,-42,null,null,98,-40,70,-26,24,null,null,null,null,92,72,-27,null,null,null,null,null,null,-67,null,null,null,null,null,null,null,-54,-66,-36,null,-72,null,null,43,null,null,null,-92,-1,-98,null,null,null,null,null,null,null,39,-84,null,null,null,null,null,null,null,null,null,null,null,null,null,-93,null,null,null,98]

【问题讨论】:

  • 是否可以选择使用特殊值(例如您的示例中的 -1)来存储空值(空节点)?
  • 不完全确定你想在这里实现什么
  • 我相信他正在尝试使用数组来表示一棵树,并找到了显示完整树示例的博客,所以他想知道当树不完整时如何做到这一点。跨度>
  • 会有节点脱离“空”节点吗?还是您希望那些空节点成为该分支的停止点?
  • 编辑我的问题更清楚。现在,输入可以被视为一个字符串。拆分后,如果可以将元素转换为 int 值,则创建节点。否则,跳过。

标签: data-structures binary-tree


【解决方案1】:

我认为这个例子可以解释你的想法。

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

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

以上所有答案都将输入数组视为一棵完整的树。所以 left.child=2idx+1 , right.child = 2idx+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;
}

【讨论】:

  • 啊太棒了!正是我要找的!谢谢
【解决方案2】:

将二叉树实现为数组时,有一个 清楚地显示两种表示如何镜像一个 另一个,并回顾下划线的数学结构 关系。

如果我们考虑 0-indexed 数组,数学关系可以 被这样分解,

  • 根节点的索引为 0

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

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

所以,对于二叉树

如果我们让- 表示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 =&gt; b
  • 右:2*(0 + 1) = 2 =&gt; 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)    
}

【讨论】:

    【解决方案3】:

    只需使用递归遍历使用数组索引的节点,使用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;
    }
    

    【讨论】:

    • 没有。那是行不通的。这将允许从一个空的根节点创建一个子树,这不是 OP 所要求的。
    【解决方案4】:

    谢谢史蒂文。我将 Steven 的 Java 代码转换为 Python。它对我有用!

    class TreeNode:
        def __init__(self, val=0, left=None, right=None):
            self.val = val
            self.left = left
            self.right = right
    
    def creatBTree(data):
        if data == None or len(data) == 0:
            return None
    
        treeNodeQueue = []
        integerQueue = []
    
        for i in range(1,len(data)):
            print(i)
            integerQueue.append(data[i])
    
        treeNode = TreeNode(data[0])
        treeNodeQueue.append(treeNode)
    
        while integerQueue:
            if integerQueue:
                leftVal = integerQueue.pop(0)
            if integerQueue:
                rightVal = integerQueue.pop(0)
    
            current = treeNodeQueue.pop(0)
    
            if leftVal is not None:
                left = TreeNode(leftVal)
                current.left = left
                treeNodeQueue.append(left)
            if rightVal is not None:
                right = TreeNode(rightVal)
                current.right = right
                treeNodeQueue.append(right)
    
        return treeNode
    

    【讨论】:

      【解决方案5】:

      在 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;
          }
      }
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2020-08-24
        • 2021-11-23
        相关资源
        最近更新 更多