Open In App

Construct tree from ancestor matrix

Last Updated : 20 Feb, 2023
Improve
Improve
Like Article
Like
Save
Share
Report

Given an ancestor matrix mat[n][n] where Ancestor matrix is defined as below. 

mat[i][j] = 1 if i is ancestor of j
mat[i][j] = 0, otherwise

Construct a Binary Tree from a given ancestor matrix where all its values of nodes are from 0 to n-1.

  1. It may be assumed that the input provided in the program is valid and the tree can be constructed out of it.
  2. Many Binary trees can be constructed from one input. The program will construct any one of them.

Examples: 

Input: 0 1 1
       0 0 0 
       0 0 0 
Output: Root of one of the below trees.
    0                0
  /   \     OR     /   \
 1     2          2     1

Input: 0 0 0 0 0 0 
       1 0 0 0 1 0 
       0 0 0 1 0 0 
       0 0 0 0 0 0 
       0 0 0 0 0 0 
       1 1 1 1 1 0
Output: Root of one of the below trees.
      5              5               5
   /    \           / \            /   \
  1      2   OR    2   1    OR    1     2  OR ....
 /  \   /        /    /  \       / \    /
0   4  3        3    0    4     4   0  3
There are different possible outputs because ancestor
matrix doesn't store that which child is left and which
is right.

We strongly recommend you to minimize your browser and try this yourself first. 

Observations used in the solution: 

  1. The rows that correspond to leaves have all 0’s
  2. The row that corresponds to root has maximum number of 1’s.
  3. Count of 1’s in i’th row indicates number of descendants of node i.

The idea is to construct the tree in bottom up manner.

  1. Create an array of node pointers node[].
  2. Store row numbers that correspond to a given count. We have used multimap for this purpose.
  3. Process all entries of multimap from smallest count to largest (Note that entries in map and multimap can be traversed in sorted order). Do following for every entry.
    • Create a new node for current row number.
    • If this node is not a leaf node, consider all those descendants of it whose parent is not set, make current node as its parent.
  4. The last processed node (node with maximum sum) is root of tree.

Below is the implementation of the above approach:

C++




// Given an ancestor matrix for binary tree, construct
// the tree.
#include <bits/stdc++.h>
using namespace std;
   
# define N 6
   
/* A binary tree node */
struct Node
{
    int data;
    Node *left, *right;
};
   
/* Helper function to create a new node */
Node* newNode(int data)
{
    Node* node = new Node;
    node->data = data;
    node->left = node->right = NULL;
    return (node);
}
   
// Constructs tree from ancestor matrix
Node* ancestorTree(int mat[][N])
{
    // Binary array to determine whether
    // parent is set for node i or not
    int parent[N] = {0};
   
    // Root will store the root of the constructed tree
    Node* root = NULL;
   
    // Create a multimap, sum is used as key and row
    // numbers are used as values
    multimap<int, int> mm;
   
    for (int i = 0; i < N; i++)
    {
        int sum = 0; // Initialize sum of this row
        for (int j = 0; j < N; j++)
            sum += mat[i][j];
   
        // insert(sum, i) pairs into the multimap
        mm.insert(pair<int, int>(sum, i));
    }
   
    // node[i] will store node for i in constructed tree
    Node* node[N];
   
    // Traverse all entries of multimap.  Note that values
    // are accessed in increasing order of sum
    for (auto it = mm.begin(); it != mm.end(); ++it)
    {
      // create a new node for every value
      node[it->second] = newNode(it->second);
   
      // To store last processed node. This node will be
      // root after loop terminates
      root = node[it->second];
   
      // if non-leaf node
      if (it->first != 0)
      {
        // traverse row 'it->second' in the matrix
        for (int i = 0; i < N; i++)
        {
           // if parent is not set and ancestor exits
           if (!parent[i] && mat[it->second][i])
           {
             // check for unoccupied left/right node
             // and set parent of node i
             if (!node[it->second]->left)
               node[it->second]->left = node[i];
             else
               node[it->second]->right = node[i];
   
             parent[i] = 1;
           }
        }
      }
    }
    return root;
}
   
/* Given a binary tree, print its nodes in inorder */
void printInorder(Node* node)
{
    if (node == NULL)
        return;
    printInorder(node->left);
    printf("%d ", node->data);
    printInorder(node->right);
}
   
// Driver code
int main()
{
    int mat[N][N] = {{ 0, 0, 0, 0, 0, 0 },
        { 1, 0, 0, 0, 1, 0 },
        { 0, 0, 0, 1, 0, 0 },
        { 0, 0, 0, 0, 0, 0 },
        { 0, 0, 0, 0, 0, 0 },
        { 1, 1, 1, 1, 1, 0 }
    };
   
    Node* root = ancestorTree(mat);
   
    cout << "Inorder traversal of tree is \n";
     
    // Function call
    printInorder(root);
   
    return 0;
}


Java




// Given an ancestor matrix for binary tree, construct
// the tree.
import java.util.HashMap;
import java.util.LinkedHashMap;
import java.util.Map;
import java.util.stream.Collectors;
 
/* A binary tree node */
class Node {
    int data;
    Node left, right;
 
    Node(int d)
    {
        data = d;
        left = right = null;
    }
}
 
public class TreeFromAncestorMatrix {
 
    static Node ancestorNode(int[][] mat)
    {
        int n = mat.length;
 
        // Binary array to determine whether parent is set
        // for node i or not
        int[] parent = new int[n];
        Node root = null;
 
        // Map to store row numbers as key and
        // their sum as their values
        Map<Integer, Integer> map = new HashMap<>();
 
        for (int i = 0; i < n; i++) {
            int sum = 0;
 
            for (int j = 0; j < n; j++)
                sum += mat[i][j];
 
            map.put(i, sum);
        }
 
        // node[i] will store node for i in
        //constructed tree
        Node node[] = new Node[n];
 
        // Sorting the map according to its
        //values
        Map<Integer, Integer> sorted
            = map.entrySet()
                  .stream()
                  .sorted(Map.Entry.comparingByValue())
                  .collect(Collectors.toMap(
                      e
                      -> e.getKey(),
                      e
                      -> e.getValue(),
                      (e1, e2) -> e2, LinkedHashMap::new));
 
        // Traverse all entries of sorted Map.
        // Note that values are accessed in increasing order
        // of sum
        for (Map.Entry<Integer, Integer> entry :
             sorted.entrySet()) {
            int key = entry.getKey();
            int value = entry.getValue();
 
            // create a new node for every
            // value
            node[key] = new Node(key);
 
            // if it is an internal node
            if (value != 0) {
 
                // Traverse row
                //corresponding to the node
                for (int i = 0; i < n; i++)
                {
 
                    // if parent is not set and
                    //ancestor exits
                    if (parent[i] == 0
                        && mat[key][i] != 0)
                    {
                        // check for unoccupied
                        // left/right node and
                        //set parent of node i
                        if (node[key].left == null)
                            node[key].left = node[i];
                        else
                            node[key].right = node[i];
                        parent[i] = 1;
                    }
 
                    // To store last processed
                    // node. This node will be root after
                    // loop terminates
                    root = node[key];
                }
            }
        }
 
        return root;
    }
  
    /* Given a binary tree, print its nodes in inorder */
    static void inOrder(Node root)
    {
        if (root == null)
            return;
        inOrder(root.left);
        System.out.print(root.data + " ");
        inOrder(root.right);
    }
 
    // Driver code
    public static void main(String[] args)
    {
        int mat[][] = {
            { 0, 0, 0, 0, 0, 0 }, { 1, 0, 0, 0, 1, 0 },
            { 0, 0, 0, 1, 0, 0 }, { 0, 0, 0, 0, 0, 0 },
            { 0, 0, 0, 0, 0, 0 }, { 1, 1, 1, 1, 1, 0 }
        };
 
        Node root = ancestorNode(mat);
 
         // Function call
        inOrder(root);
    }
}
 
// contribute by amarsomani


Python3




# key structure to store a binary tree node
class Node:
    def __init__(self, key, left = None, right = None):
        self.key = key
        self.left = left
        self.right = right
 
# Utility function to print binary tree nodes in-order fashion
def inorder(node):
    if node:
        inorder(node.left)
        print(node.key, end = ' ')
        inorder(node.right)
 
# Function to construct a binary tree
# from specified ancestor matrix
def constructBT(mat):
   
    # get number of rows in the matrix
    N = len(mat)
 
    # create an empty multi-dict
    dict = {}
 
    # Use sum as key and row numbers as values in the multi-dict
    for i in range(N):
 
        # find the sum of the current row
        total = sum(mat[i])
 
        # insert the sum and row number into the dict
        dict.setdefault(total, []).append(i)
 
    # node[i] will store node for i in constructed tree
    node = [Node(-1)] * N
    last = 0
 
    # the value of parent[i] is true if parent is set for i'th node
    parent = [False] * N
 
    # Traverse the dictionary in sorted order (default behavior)
    for key in dict.keys():
        for row in dict.get(key):
            last = row
             
            # create a new node
            node[row] = Node(row)
 
            # if leaf node, do nothing
            if key == 0:
                continue
 
            # traverse row
            for i in range(N):
               
                # do if parent is not set and ancestor exits
                if not parent[i] and mat[row][i] == 1:
                   
                    # check for the unoccupied node
                    if node[row].left is None:
                        node[row].left = node[i]
                    else:
                        node[row].right = node[i]
 
                    # set parent for i'th node
                    parent[i] = True
 
    # last processed node is the root
    return node[last]
 
# Construct a Binary Tree from Ancestor Matrix
if __name__ == '__main__':
 
    mat = [[0, 0, 0, 0, 0, 0],
        [1, 0, 0, 0, 1, 0],
        [0, 0, 0, 1, 0, 0],
        [0, 0, 0, 0, 0, 0],
        [0, 0, 0, 0, 0, 0],
        [1, 1, 1, 1, 0, 0]]
 
    root = constructBT(mat)
    inorder(root)
 
# This code is contributed by Priyadarshini Kumari


C#




// Given an ancestor matrix for binary tree, construct
// the tree.
using System;
using System.Collections.Generic;
using System.Linq;
 
/* A binary tree node */
public
  class Node
  {
    public
      int data;
    public
      Node left, right;
    public
      Node(int d)
    {
      data = d;
      left = right = null;
    }
  }
 
public class TreeFromAncestorMatrix
{
 
  static Node ancestorNode(int[,] mat)
  {
    int n = mat.GetLength(0);
 
    // Binary array to determine whether parent is set
    // for node i or not
    int[] parent = new int[n];
    Node root = null;
 
    // Map to store row numbers as key and
    // their sum as their values
    Dictionary<int, int> map = new Dictionary<int, int>();
    for (int i = 0; i < n; i++)
    {
      int sum = 0;
      for (int j = 0; j < n; j++)
        sum += mat[i, j];
      map.Add(i, sum);
    }
 
    // node[i] will store node for i in
    //constructed tree
    Node []node = new Node[n];
 
    var sorted = from entry in map orderby entry.Value ascending select entry;
 
    // Traverse all entries of sorted Map.
    // Note that values are accessed in increasing order
    // of sum
    foreach (KeyValuePair<int, int> entry in
             sorted)
    {
      int key = entry.Key;
      int value = entry.Value;
 
      // create a new node for every
      // value
      node[key] = new Node(key);
 
      // if it is an internal node
      if (value != 0)
      {
 
        // Traverse row
        //corresponding to the node
        for (int i = 0; i < n; i++)
        {
 
          // if parent is not set and
          //ancestor exits
          if (parent[i] == 0
              && mat[key,i] != 0)
          {
            // check for unoccupied
            // left/right node and
            //set parent of node i
            if (node[key].left == null)
              node[key].left = node[i];
            else
              node[key].right = node[i];
            parent[i] = 1;
          }
 
          // To store last processed
          // node. This node will be root after
          // loop terminates
          root = node[key];
        }
      }
    }
    return root;
  }
 
  /* Given a binary tree, print its nodes in inorder */
  static void inOrder(Node root)
  {
    if (root == null)
      return;
    inOrder(root.left);
    Console.Write(root.data + " ");
    inOrder(root.right);
  }
 
  // Driver code
  public static void Main(String[] args)
  {
    int [,]mat = {
      { 0, 0, 0, 0, 0, 0 }, { 1, 0, 0, 0, 1, 0 },
      { 0, 0, 0, 1, 0, 0 }, { 0, 0, 0, 0, 0, 0 },
      { 0, 0, 0, 0, 0, 0 }, { 1, 1, 1, 1, 1, 0 }
    };
    Node root = ancestorNode(mat);
 
    // Function call
    inOrder(root);
  }
}
 
// This code is contributed by Rajput-Ji


Javascript




<script>
 
// Given an ancestor matrix for binary tree, construct
// the tree.
 
/* A binary tree node */
class Node
{
  constructor(d)
  {
    this.data = d;
    this.left = null;
    this.right = null;
  }
}
 
 function ancestorNode( mat)
{
  var n = mat.length;
   
  // Binary array to determine whether parent is set
  // for node i or not
  var parent = Array(n).fill(0);
  var root = null;
   
  // Map to store row numbers as key and
  // their sum as their values
  var map = new Map();
 
  for(var i = 0; i < n; i++)
  {
    var sum = 0;
    for (var j = 0; j < n; j++)
      sum += mat[i][j];
    map.set(i, sum);
  }
   
  // node[i] will store node for i in
  //constructed tree
  var node = Array(n).fill(null);
 
  // Traverse all entries of sorted Map.
  // Note that values are accessed in increasing order
  // of sum
  for(var data of [...map].sort((a,b)=> a[1]-b[1]))
  {
    
    var key = data[0];
    var value = data[1];
 
    // create a new node for every
    // value
    node[key] = new Node(key);
     
    // if it is an internal node
    if (value != 0)
    {
     
      // Traverse row
      //corresponding to the node
      for (var i = 0; i < n; i++)
      {
       
        // if parent is not set and
        //ancestor exits
        if (parent[i] == 0
            && mat[key][i] != 0)
        {
         
          // check for unoccupied
          // left/right node and
          //set parent of node i
          if (node[key].left == null)
            node[key].left = node[i];
          else
            node[key].right = node[i];
          parent[i] = 1;
        }
         
        // To store last processed
        // node. This node will be root after
        // loop terminates
        root = node[key];
      }
    }
  };
 
  return root;
}
 
/* Given a binary tree, print its nodes in inorder */
function inOrder(root)
{
  if (root == null)
    return;
  inOrder(root.left);
  document.write(root.data + " ");
  inOrder(root.right);
}
 
// Driver code
var mat = [
  [ 0, 0, 0, 0, 0, 0 ], [ 1, 0, 0, 0, 1, 0 ],
  [ 0, 0, 0, 1, 0, 0 ], [ 0, 0, 0, 0, 0, 0 ],
  [ 0, 0, 0, 0, 0, 0 ], [ 1, 1, 1, 1, 1, 0 ]
];
var root = ancestorNode(mat);
 
// Function call
inOrder(root);
 
// This code is contributed by rdtank.
</script>


Output

0 1 4 5 3 2

Time Complexity: O(N2), where N is the number of nodes in the tree.
Space Complexity: O(N2), where N is the number of nodes in the tree.

Note that we can also use an array of vectors in place of multimap. We have used multimap for simplicity. Array of vectors would improve performance as inserting and accessing elements would take O(1) time.



Previous Article
Next Article

Similar Reads

Construct Binary Tree from Ancestor Matrix | Top Down Approach
Given an ancestor matrix mat[n][n] where the ancestor matrix is defined as below. mat[i][j] = 1 if i is ancestor of j mat[i][j] = 0, otherwise Construct a Binary Tree from the given ancestor matrix where all its values of nodes are from 0 to n-1. It may be assumed that the input provided by the program is valid and the tree can be constructed out o
10 min read
Construct Ancestor Matrix from a Given Binary Tree
Given a Binary Tree where all values are from 0 to n-1. Construct an ancestor matrix mat[n][n]. Ancestor matrix is defined as below. mat[i][j] = 1 if i is ancestor of j mat[i][j] = 0, otherwise Examples: Input: Root of below Binary Tree. 0 / \ 1 2 Output: 0 1 1 0 0 0 0 0 0 Input: Root of below Binary Tree. 5 / \ 1 2 / \ / 0 4 3 Output: 0 0 0 0 0 0
15 min read
Lowest Common Ancestor in a Binary Tree | Set 3 (Using RMQ)
Given a rooted tree, and two nodes are in the tree, find the Lowest common ancestor of both the nodes. The LCA for two nodes u and v is defined as the farthest node from the root that is the ancestor to both u and v. Prerequisites: LCA | SET 1 Example for the above figure : Input : 4 5 Output : 2 Input : 4 7 Output : 1 Converting LCA to RMQ(Range M
15+ min read
K-th ancestor of a node in Binary Tree | Set 3
Given a binary tree in which nodes are numbered from 1 to N. Given a node and a positive integer K. We have to print the Kth ancestor of the given node in the binary tree. If there does not exist any such ancestor then print -1.For example in the below given binary tree, 2nd ancestor of node 4 and 5 is 1. 3rd ancestor of node 4 will be -1. Approach
7 min read
Kth ancestor of a node in an N-ary tree using Binary Lifting Technique
Given a vertex V of an N-ary tree and an integer K, the task is to print the Kth ancestor of the given vertex in the tree. If there does not exist any such ancestor then print -1.Examples: Input: K = 2, V = 4 Output: 1 2nd parent of vertex 4 is 1.Input: K = 3, V = 4 Output: -1 Approach: The idea is to use Binary Lifting Technique. This technique is
9 min read
Least Common Ancestor of any number of nodes in Binary Tree
Given a binary tree (not a binary search tree) and any number of Key Nodes, the task is to find the least common ancestor of all the key Nodes. Following is the definition of LCA from Wikipedia: Let T be a rooted tree. The lowest common ancestor between two nodes n1 and n2 is defined as the lowest node in T that has both n1 and n2 as descendants (w
9 min read
Lowest Common Ancestor for a Set of Nodes in a Rooted Tree
Given a rooted tree with N nodes, the task is to find the Lowest Common Ancestor for a given set of nodes V of that tree. Examples: Input: 1 / | \ 2 3 4 / \ | | 5 6 7 10 / \ 8 9 V[] = {7, 3, 8, 9} Output: 3 Input: 1 / | \ 2 3 4 / \ | | 5 6 7 10 / \ 8 9 V[] = {4, 6, 7} Output: 1 Approach: We can observe that the Lowest Common Ancestors for any set o
12 min read
Kth ancestor of all nodes in an N-ary tree using DFS
Given an N-ary tree and an integer K, the task is to print the Kth ancestors of all the nodes of the tree in level order manner. If K ancestors does not exist for a node, then print -1 for that node. Examples: Input: K = 2 Output: -1 -1 -1 1 1 1 1 1 1 Explanation: 2nd ancestor does not exist for nodes 1, 2 and 3 2nd ancestor of nodes 4, 5, 6, 7, 8,
9 min read
Lowest Common Ancestor of the deepest leaves of a Binary Tree
Given a Binary Tree consisting of N nodes having distinct values from the range [1, N], the task is to find the lowest common ancestor of the deepest leaves of the binary tree. Examples: Input: Output: 1Explanation: The deepest leaf nodes of the tree are {8, 9, 10}. Lowest common ancestor of these nodes is 1. Input: Output: 6 Approach: The given pr
10 min read
Maximize difference between pair of nodes in a given rooted tree such that one node is ancestor of another
Given a Generic Tree consisting of N nodes valued from 0 to (N - 1) where P[i]th in the array P[] denotes ith nodes parent(1-based indexing). Each ith node has a weight attached to it, given in the array W[]. The task is to find a pair of nodes (u, v), such that u is an ancestor of v, and Wu - Wv is maximized. Note: In the array P[], -1 denotes the
14 min read
Article Tags :
Practice Tags :