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]

8
  • Is it an option to use special values (like -1 in your example) to store nulls (empty nodes)? Commented Jun 21, 2016 at 12:25
  • 1
    Not exactly sure what you're trying to achieve here Commented Jun 21, 2016 at 12:41
  • 1
    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. Commented Jun 21, 2016 at 14:48
  • Will you have nodes going off the "null" nodes? Or will you want those null nodes to be stopping points for that branch? Commented Jun 21, 2016 at 16:55
  • 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. Commented Jun 21, 2016 at 16:57

6 Answers 6

23

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;
}
Sign up to request clarification or add additional context in comments.

Comments

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)    
}

Comments

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

3 Comments

This does not work for arr = [1, 2, 3, None, Now, 5, 6, None, None, None, None 7, 8]
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 list
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]
0

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

1 Comment

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.
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)

Comments

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

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.