Open In App

Create Binary Tree from given Array of relation between nodes

Last Updated : 29 Dec, 2022
Improve
Improve
Like Article
Like
Save
Share
Report

Given a 2D integer array where each row represents the relation between the nodes (relation[i] = [parenti, childi, isLefti]). The task is to construct the binary tree described by the 2D matrix and print the LevelOrder Traversal of the formed Binary Tree.

Examples:

Input: Relation[] = [[20, 15, 1], [20, 17, 0], [50, 20, 1], [50, 80, 0], [80, 19, 1]]
Output: [50, 20, 80, 15, 17, 19]
Explanation: The root node is the node with the value 50 since it has no parent.

Example1

Input: Relation[] = [[1, 2, 1], [2, 3, 0], [3, 4, 1]]
Output: [1, 2, 3, 4]
Explanation: The root node is the node with the value 1 since it has no parent.

Example 2

Approach: To solve the problem follow the below idea:

Iterate over the given 2D matrix(Relation Array) and see if the parent Node is present in the map or not.

Follow the Below steps to solve the above approach:

  • Create a map data Structure that will store the address of each of the nodes formed with their values.
  •  Iterate over the given 2D matrix(Relation Array) and see if the parentNode is present in the map or not. 
    • If the parentNode is present in the map then there is no need of making a new node, Just store the address of the parentNode in a variable. 
    • If the parentNode is not present in the map then form a parentNode of the given value and store its address in the map. (Because this parentNode can be the childNode of some other Node). 
  • Similarly, Repeat Step 2 for child Node also i.e.,
    • If the childNode is present in the map then there is no need of making a new node, Just store the address of the childNode in a variable.
    • If the childNode is not present in the map then form a childNode of the given value and store its address in the map(Because this childNode can be the parentNode of some other Node). 
  •  Form the relation between the parentNode and the childNode for each iteration depending on the value of the third value of the array of each iteration. i.e.,
    • If the third value of the array in the given iteration is 1 then it means that the childNode is the left child of the parentNode formed for the given iteration.
    • If the third value of the array in the given iteration is 0 then it means that the childNode is the left child of the parentNode formed for the given iteration.
  • If carefully observed we know that the root node is the only node that has no Parent.
  • Store all the values of the childNode that is present in the given 2D matrix (Relation Array) in a data structure (let’s assume a map data structure).
  • Again iterate the 2D matrix (RelationArray) to check which parentNode value is not present in the map data structure formed in step 5).
  • Print the level Order Traversal of the thus-formed tree.  

Below is the implementation of the above approach.

C++




// C++ code for the above approach:
#include <bits/stdc++.h>
using namespace std;
 
// Binary Tree Node
struct Node {
    int data;
    Node *left, *right;
};
 
// Returns new Node with data as input
// to below function.
Node* newNode(int d)
{
    Node* temp = new Node;
    temp->data = d;
    temp->left = nullptr;
    temp->right = nullptr;
    return temp;
}
 
// Function to create tree from
// given description
Node* createBinaryTree(vector<vector<int> >& descriptions)
{
    unordered_map<int, Node*> mp;
    for (auto it : descriptions) {
        Node *parentNode, *childNode;
 
        // Check if the parent Node is
        // already formed or not
        if (mp.find(it[0]) != mp.end()) {
            parentNode = mp[it[0]];
        }
        else {
            parentNode = newNode(it[0]);
            mp[it[0]] = parentNode;
        }
 
        // Check if the child Node is
        // already formed or not
        if (mp.find(it[1]) != mp.end()) {
            childNode = mp[it[1]];
        }
        else {
            childNode = newNode(it[1]);
            mp[it[1]] = childNode;
        }
 
        // Making the Edge Between parent
        // and child Node
        if (it[2] == 1) {
            parentNode->left = childNode;
        }
        else {
            parentNode->right = childNode;
        }
    }
 
    // Store the childNode
    unordered_map<int, int> storeChild;
    for (auto it : descriptions) {
        storeChild[it[1]] = 1;
    }
 
    // Find the root of the Tree
    Node* root;
    for (auto it : descriptions) {
        if (storeChild.find(it[0]) == storeChild.end()) {
            root = mp[it[0]];
        }
    }
    return root;
}
 
// Level order Traversal
void printLevelOrder(Node* root)
{
 
    // Base Case
    if (root == nullptr) {
        return;
    }
 
    // Create an empty queue for
    // level order traversal
    queue<Node*> q;
 
    // Enqueue Root and initialize height
    q.push(root);
    while (q.empty() == false) {
 
        // Print front of queue and
        // remove it from queue
        Node* node = q.front();
        cout << node->data << " ";
        q.pop();
 
        // Enqueue left child
        if (node->left != nullptr) {
            q.push(node->left);
        }
 
        // Enqueue right child
        if (node->right != nullptr) {
            q.push(node->right);
        }
    }
}
 
// Driver Code
int main()
{
    vector<vector<int> > RelationArray = { { 20, 15, 1 },
                                           { 20, 17, 0 },
                                           { 50, 20, 1 },
                                           { 50, 80, 0 },
                                           { 80, 19, 1 } };
    Node* root = createBinaryTree(RelationArray);
    printLevelOrder(root);
    cout << endl;
    vector<vector<int> > RelationArray2
        = { { 1, 2, 1 }, { 2, 3, 0 }, { 3, 4, 1 } };
    Node* root2 = createBinaryTree(RelationArray2);
    printLevelOrder(root2);
    return 0;
}


Java




// Java code for the above approach:
import java.io.*;
import java.util.*;
 
// Binary Tree Node
class Node {
  int data;
  Node left, right;
 
  Node(int d)
  {
    data = d;
    left = right = null;
  }
}
 
class GFG {
 
  // Returns new Node with data as input
  // to below function.
  static Node newNode(int d)
  {
    Node temp = new Node(d);
    temp.left = null;
    temp.right = null;
    return temp;
  }
 
  // Function to create tree from
  // given description
  static Node
    createBinaryTree(List<List<Integer> > descriptions)
  {
    Map<Integer, Node> mp = new HashMap<>();
    for (List<Integer> it : descriptions) {
      Node parentNode, childNode;
 
      // Check if the parent Node is
      // already formed or not
      if (mp.containsKey(it.get(0))) {
        parentNode = mp.get(it.get(0));
      }
      else {
        parentNode = newNode(it.get(0));
        mp.put(it.get(0), parentNode);
      }
 
      // Check if the child Node is
      // already formed or not
      if (mp.containsKey(it.get(1))) {
        childNode = mp.get(it.get(1));
      }
      else {
        childNode = newNode(it.get(1));
        mp.put(it.get(1), childNode);
      }
 
      // Making the Edge Between parent
      // and child Node
      if (it.get(2) == 1) {
        parentNode.left = childNode;
      }
      else {
        parentNode.right = childNode;
      }
    }
 
    // Store the childNode
    Map<Integer, Integer> storeChild = new HashMap<>();
    for (List<Integer> it : descriptions) {
      storeChild.put(it.get(1), 1);
    }
 
    // Find the root of the Tree
    Node root = null;
    for (List<Integer> it : descriptions) {
      if (!storeChild.containsKey(it.get(0))) {
        root = mp.get(it.get(0));
      }
    }
    return root;
  }
 
  // Level order Traversal
  static void printLevelOrder(Node root)
  {
    // Base Case
    if (root == null) {
      return;
    }
 
    // Create an empty queue for
    // level order traversal
    Queue<Node> q = new LinkedList<>();
 
    // Enqueue Root and initialize height
    q.add(root);
    while (!q.isEmpty()) {
      // Print front of queue and
      // remove it from queue
      Node node = q.peek();
      System.out.print(node.data + " ");
      q.poll();
 
      // Enqueue left child
      if (node.left != null) {
        q.add(node.left);
      }
 
      // Enqueue right child
      if (node.right != null) {
        q.add(node.right);
      }
    }
  }
 
  public static void main(String[] args)
  {
    List<List<Integer> > RelationArray
      = Arrays.asList(Arrays.asList(20, 15, 1),
                      Arrays.asList(20, 17, 0),
                      Arrays.asList(50, 20, 1),
                      Arrays.asList(50, 80, 0),
                      Arrays.asList(80, 19, 1));
    Node root = createBinaryTree(RelationArray);
    printLevelOrder(root);
    System.out.println();
    List<List<Integer> > RelationArray2 = Arrays.asList(
      Arrays.asList(1, 2, 1), Arrays.asList(2, 3, 0),
      Arrays.asList(3, 4, 1));
    Node root2 = createBinaryTree(RelationArray2);
    printLevelOrder(root2);
  }
}
 
// This code is contributed by lokeshmvs21.


Python3




# Python code for the above approach
from typing import List
 
# Binary Tree Node
class Node:
    def __init__(self, data):
        self.data = data
        self.left = None
        self.right = None
 
# Returns new Node with data as input
# to below function.
def newNode(d):
    temp = Node(d)
    return temp
 
# Function to create tree from
# given description
def createBinaryTree(descriptions: List[List[int]]) -> Node:
    mp = {}
    for it in descriptions:
        parentNode, childNode = None, None
 
        # Check if the parent Node is
        # already formed or not
        if it[0] in mp:
            parentNode = mp[it[0]]
        else:
            parentNode = newNode(it[0])
            mp[it[0]] = parentNode
 
        # Check if the child Node is
        # already formed or not
        if it[1] in mp:
            childNode = mp[it[1]]
        else:
            childNode = newNode(it[1])
            mp[it[1]] = childNode
 
        # Making the Edge Between parent
        # and child Node
        if it[2] == 1:
            parentNode.left = childNode
        else:
            parentNode.right = childNode
 
    # Store the childNode
    storeChild = {}
    for it in descriptions:
        storeChild[it[1]] = 1
 
    # Find the root of the Tree
    root = None
    for it in descriptions:
        if it[0] not in storeChild:
            root = mp[it[0]]
     
    return root
 
# Level order Traversal
def printLevelOrder(root: Node):
    # Base Case
    if root is None:
        return
 
    # Create an empty queue for
    # level order traversal
    q = []
 
    # Enqueue Root and initialize height
    q.append(root)
    while len(q) > 0:
        # Print front of queue and
        # remove it from queue
        node = q.pop(0)
        print(node.data, end=' ')
 
        # Enqueue left child
        if node.left is not None:
            q.append(node.left)
 
        # Enqueue right child
        if node.right is not None:
            q.append(node.right)
 
# Driver Code
if __name__ == "__main__":
    relationArray = [[20, 15, 1], [20, 17, 0], [50, 20, 1], [50, 80, 0], [80, 19, 1]]
    root = createBinaryTree(relationArray)
    printLevelOrder(root)
    print()
    relationArray2 = [[1, 2, 1], [2, 3, 0], [3, 4, 1]]
    root2 = createBinaryTree(relationArray2)
    printLevelOrder(root2)
     
# This code is contributed by Potta Lokesh


C#




// C# code for the above approach:
using System;
using System.Collections.Generic;
using System.Linq;
 
// Binary Tree Node
class Node {
  public int data;
  public Node left, right;
 
  public Node(int data)
  {
    this.data = data;
    this.left = null;
    this.right = null;
  }
}
 
public class GFG {
 
  // Returns new Node with data as input
  // to below function.
  static Node NewNode(int data)
  {
    Node temp = new Node(data);
    temp.left = null;
    temp.right = null;
    return temp;
  }
 
  // Function to create tree from
  // given description
  static Node
    CreateBinaryTree(List<List<int> > descriptions)
  {
    Dictionary<int, Node> mp
      = new Dictionary<int, Node>();
    foreach(List<int> it in descriptions)
    {
      Node parentNode, childNode;
 
      // Check if the parent Node is
      // already formed or not
      if (mp.ContainsKey(it[0])) {
        parentNode = mp[it[0]];
      }
      else {
        parentNode = NewNode(it[0]);
        mp[it[0]] = parentNode;
      }
 
      // Check if the child Node is
      // already formed or not
      if (mp.ContainsKey(it[1])) {
        childNode = mp[it[1]];
      }
      else {
        childNode = NewNode(it[1]);
        mp[it[1]] = childNode;
      }
 
      // Making the Edge Between parent
      // and child Node
      if (it[2] == 1) {
        parentNode.left = childNode;
      }
      else {
        parentNode.right = childNode;
      }
    }
 
    // Store the childNode
    Dictionary<int, int> storeChild
      = new Dictionary<int, int>();
    foreach(List<int> it in descriptions)
    {
      storeChild[it[1]] = 1;
    }
 
    // Find the root of the Tree
    Node root = null;
    foreach(List<int> it in descriptions)
    {
      if (!storeChild.ContainsKey(it[0])) {
        root = mp[it[0]];
      }
    }
    return root;
  }
 
  // Level order Traversal
  static void PrintLevelOrder(Node root)
  {
    // Base Case
    if (root == null) {
      return;
    }
 
    // Create an empty queue for
    // level order traversal
    Queue<Node> q = new Queue<Node>();
 
    // Enqueue Root and initialize height
    q.Enqueue(root);
    while (q.Count > 0) {
      // Print front of queue and
      // remove it from queue
      Node node = q.Peek();
      Console.Write(node.data + " ");
      q.Dequeue();
 
      // Enqueue left child
      if (node.left != null) {
        q.Enqueue(node.left);
      }
 
      // Enqueue right child
      if (node.right != null) {
        q.Enqueue(node.right);
      }
    }
  }
 
  static public void Main()
  {
    List<List<int> > RelationArray
      = new List<List<int> >{
      new List<int>{ 20, 15, 1 },
      new List<int>{ 20, 17, 0 },
      new List<int>{ 50, 20, 1 },
      new List<int>{ 50, 80, 0 },
      new List<int>{ 80, 19, 1 }
    };
    Node root = CreateBinaryTree(RelationArray);
    PrintLevelOrder(root);
    Console.WriteLine();
    List<List<int> > RelationArray2
      = new List<List<int> >{
      new List<int>{ 1, 2, 1 },
      new List<int>{ 2, 3, 0 },
      new List<int>{ 3, 4, 1 }
    };
    Node root2 = CreateBinaryTree(RelationArray2);
    PrintLevelOrder(root2);
  }
}
 
// This code is contributed by lokesh.


Javascript




// JavaScript Code for the above approach
 
// Node Class
class Node {
    constructor(data) {
        this.data = data;
        this.left = null;
        this.right = null;
    }
}
 
// Function to create tree from given description
function createBinaryTree(descriptions) {
    let mp = new Map();
    for (let it of descriptions) {
        let parentNode, childNode;
 
        // Check if the parent Node is
        // already formed or not
        if (mp.has(it[0])) {
            parentNode = mp.get(it[0]);
        }
        else {
            parentNode = new Node(it[0]);
            mp.set(it[0], parentNode);
        }
 
        // Check if the child Node is
        // already formed or not
        if (mp.has(it[1])) {
            childNode = mp.get(it[1]);
        }
        else {
            childNode = new Node(it[1]);
            mp.set(it[1], childNode);
        }
 
        // Making the Edge Between parent
        // and child Node
        if (it[2] == 1) {
            parentNode.left = childNode;
        }
        else {
            parentNode.right = childNode;
        }
    }
 
    // Store the childNode
    let storeChild = new Map();
    for (let it of descriptions) {
        storeChild.set(it[1], 1);
    }
 
    // Find the root of the Tree
    let root;
    for (let it of descriptions) {
        if (!storeChild.has(it[0])) {
            root = mp.get(it[0]);
        }
    }
    return root;
}
 
// Level order Traversal
function printLevelOrder(root) {
    // Base Case
    if (root == null) {
        return;
    }
 
    // Create an empty queue for
    // level order traversal
    let q = [];
 
    // Enqueue Root and initialize height
    q.push(root);
    while (q.length > 0) {
 
        // Print front of queue and
        // remove it from queue
        let node = q.shift();
        console.log(node.data + " ");
 
        // Enqueue left child
        if (node.left != null) {
            q.push(node.left);
        }
 
        // Enqueue right child
        if (node.right != null) {
            q.push(node.right);
        }
    }
}
 
// Driver Code
let RelationArray = [
    [20, 15, 1],
    [20, 17, 0],
    [50, 20, 1],
    [50, 80, 0],
    [80, 19, 1],
];
let root = createBinaryTree(RelationArray);
printLevelOrder(root);
let RelationArray2 = [
    [1, 2, 1],
    [2, 3, 0],
    [3, 4, 1],
];
let root2 = createBinaryTree(RelationArray2);
printLevelOrder(root2);
 
// This code is contributed by adityamaharshi21


Output

50 20 80 15 17 19 1 2 3 4 

Time Complexity: O(N) where N is the number of rows present in the 2D matrix + O(M) where M is the number of nodes present in the Tree (for Level Order Traversal)
Auxiliary Space: O(M) where M is the number of nodes present in the Tree (We are storing the values of the nodes along with their address in the map). 

Related Articles:



Like Article
Suggest improvement
Share your thoughts in the comments

Similar Reads