How to build an incomplete binary tree from array representation
Asked Answered
B

6

9

if the input is an array, where null means no node.

input:

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

Please assume that I have already checked the input.

For each array[i], its parents array[i / 2] will not be null (recursively, so root can not be null).

How to build a tree with such logic relation:

   1
 /    \
2      3
 \      \ 
  5      7

each node should be represented by a TreeNode object:

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

I found a blog here where a complete tree was built

but if the tree is incomplete as mentioned above, how to do it neatly and efficiently ?

Test data:

[input array]

[-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]

Benzoate answered 21/6, 2016 at 10:1 Comment(8)
Is it an option to use special values (like -1 in your example) to store nulls (empty nodes)?Reredos
Not exactly sure what you're trying to achieve herePeepul
I believe he's trying to represent a tree by using an array, and found the blog which shows the example with the complete tree, so he's wondering how to do that when the tree is not complete.Reredos
Will you have nodes going off the "null" nodes? Or will you want those null nodes to be stopping points for that branch?Sailesh
edited my question to be more clear. Now, the input could be treated as a string. After splitting it, if an element could be converted into an int value, a node is created. Otherwise, skip.Benzoate
"null" means no node created at that logic position, the branch stops there.Benzoate
what would the tree look like if the input is [null, 2, 3, 4, 5, 6, 7] ?Sailesh
Please assume that I have already checked the input. For each array[i], its parentsarray[i / 2] will not be null(recursively, so root must not be null).Benzoate
A
11

When implementing a binary tree as an array it helps to have a clear visualization of how the two representations mirror one another, and review the mathematical structure that underlines the relationship.

If we consider 0-indexed arrays the mathematical relation can be broken down as such,

  • The root node has index 0

For the i:th node (i is the array index) we have that (verify)

  • The left-child of the node has the index 2i + 1
  • The right-child of the node has the index 2(i + 1)
  • The parent of a node has the index floor((i-1)/2)

So, for the binary tree

Binary tree

if we let - denote null, is represented as such

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

So now to create the OO representation from the array you simply apply these indexing rules. So, since you know that the root node is a then we get its children at:

  • Left: 2*0 + 1 = 1 => b
  • Right: 2*(0 + 1) = 2 => c

Pseudo code

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)    
}
Anthracoid answered 26/6, 2016 at 20:40 Comment(0)
G
22

I think this example can explain what's in your mind .

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

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

All answer above are regard input array as a full tree. So left.child=2idx+1 , right.child = 2idx+2 but is actually it's wrong . beacuse those

[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]

are different

here is my solution

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;
}
Gogh answered 11/6, 2019 at 9:26 Comment(1)
ah awesome! exactly what I am looking for! thanksWishywashy
A
11

When implementing a binary tree as an array it helps to have a clear visualization of how the two representations mirror one another, and review the mathematical structure that underlines the relationship.

If we consider 0-indexed arrays the mathematical relation can be broken down as such,

  • The root node has index 0

For the i:th node (i is the array index) we have that (verify)

  • The left-child of the node has the index 2i + 1
  • The right-child of the node has the index 2(i + 1)
  • The parent of a node has the index floor((i-1)/2)

So, for the binary tree

Binary tree

if we let - denote null, is represented as such

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

So now to create the OO representation from the array you simply apply these indexing rules. So, since you know that the root node is a then we get its children at:

  • Left: 2*0 + 1 = 1 => b
  • Right: 2*(0 + 1) = 2 => c

Pseudo code

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)    
}
Anthracoid answered 26/6, 2016 at 20:40 Comment(0)
C
3

Thanks Steven. I converted the Java code from Steven into Python. It worked for me!

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
Conjunction answered 30/12, 2021 at 17:17 Comment(3)
This does not work for arr = [1, 2, 3, None, Now, 5, 6, None, None, None, None 7, 8]Sundries
If you run for [1, 2, 3, None, None, 5,6,None,None,None,None, 7, 8, None, None], I ge t IndexError: pop from empty listSundries
the leftVal and rightVal need to be set to None at the top of the while loop or else you get a left over/repeated value hanging around on your node - [1,None,2,3]Dubbing
B
1

Just use recursion to traverse the nodes using the index of the array and use Integer to allow 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;
}
Barye answered 9/12, 2017 at 3:35 Comment(1)
No. That won't work. This would allow the creation of a subtree from a root node that is null which isn't what the OP was asking for.Accrescent
S
0

I have replaced null with -1 for simplicity arr = [1, 2, 3, -1, -1, 5,6,-1,-1,-1,-1, 7, 8, -1, -1] Now this given method insert will create a complete binary from above array then convertMinus1IntoNone function will remove all nodes with -1 and make proper tree as needed in question.

from collections import deque

class Node:
    def __init__(self, val):
        self.val = val
        self.left = None
        self.right = None
   
def insert(root, val):
    newnode = Node(val)
    if not root:
        root = newnode
        return root
    Q = deque([root])
    while Q:
        node = Q.popleft()
        if not node.left:
            node.left = newnode
            return
        if not node.right:
            node.right = newnode
            return
        else:
            Q.append(node.left)
            Q.append(node.right)

def convertMinus1IntoNone(root):
    if root is None:
        return
    if root.left!= None:
      convertMinus1IntoNone(root.left)
      if root.left.val == -1:
          root.left = None

    if root.right!= None:
      convertMinus1IntoNone(root.right)
      if root.right.val == -1:
          root.right = None


arr = [1, 2, 3, -1, -1, 5,6,-1,-1,-1,-1, 7, 8, -1, -1]
root = insert(None, arr[0])
for i in range(1, len(arr) , 1):
    insert(root, arr[i])
convertMinus1IntoNone(root)
Sundries answered 16/11, 2022 at 1:18 Comment(0)
D
-1

In 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;
    }
}
Deni answered 17/5, 2021 at 12:0 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.