Insertion in n-ary tree in given order and Level order traversal

• Difficulty Level : Hard
• Last Updated : 18 Aug, 2021

Given a set of parent nodes where the index of the array is the child of each Node value, the task is to insert the nodes as a forest(multiple trees combined together) where each parent could have more than two children. After inserting the nodes, print each level in a sorted format.

Example:

Input: arr[] = {5, 3, -1, 2, 5, 3}
Output:
-1
2
3
1 5
Input: arr[] = {-1, -1, -1, -1, -1, 1}
Output:
-1
0 1 2 3 4
5

Below is the explanation of the above examples:

• Example 1:
• In this given array, the elements of the array will be the parent node and the array index will be the child nodes.

• Initially, we set the root of the forest to be -1 for reference.
• Now on traversing the array, we insert the nodes into the forest structure.
• Initially we identify the roots of the individual trees in the forest and insert them into the root of the forest.

• The index of -1 is 2. Print -1 and append 2 as child node.
• Now search the list for list value as 2. Index 3 has value 2. Therefore 3 becomes the child of 2.

• Now the indexes having value 3 are 1 and 5. So 1 and 5 are the children of 3.
• The list does not contain 1 so ignore 1.
• The index that contains 5 are 0 and 4. So they become the child.
-1 ---------- root of the forest
/
2    ---------- level (0)
/
3       ---------- level (1)
/ \
1   5     ---------- level (2)
/     \
0       4       ---------- level (3)

Note: level (0) contains roots of each tree
• Example 2:
• In this case, the tree will be of the format
-1        -------- root of the forest
/ | | | \
0  1 2 3  4   -------- level (0)
|
5          -------- level (1)
Note: level (0) contains roots of each tree

Prerequisite: Level order traversal.
Approach: The idea is to recursively insert nodes in a tree. However the tree structure is quite different, usually in the case of binary tree there will be a maximum of two child nodes for any node but in this case the root node can have N number of child nodes.’-1′ is considered as the root and the index of the root will be considered as child nodes.

Example:
If -1 is present in index 3 then 3 will be the child node of -1.

-1
/
3

Insert -1 into the queue. Now if the root is empty then -1 node becomes the root. Now dequeue and queue the child nodes of -1. Create nodes and append them with the root. Continue this till all the child nodes have been inserted.

Level order Traversal:
-1
3   5
2 4 6   9
The output for level order traversal will be: -1 3 5 2 4 6 9

Same enqueue and dequeue approach is followed for traversing by level order.

Below is the implementation of the above approach:

C++

 // C++ implementation of the approach#include using namespace std; // Node creationclass Node{    public:        int val;                 // Since n children are possible for a root.        // A list created to store all the children.        vector child;                 // Constructor        Node(int data) : val(data) {}}; // Function to insertvoid insert(Node *root, int parent, Node *node){         // Root is empty then the node wil    // l become the root    if (!root)    {        root = node;    }    else    {        if (root->val == parent)        {        root->child.push_back(node);        }        else        {            // Recursive approach to            // insert the child            int l = root->child.size();                         for(int i = 0; i < l; i++)            {                if (root->child[i]->val == parent)                    insert(root->child[i], parent, node);                else                    insert(root->child[i], parent, node);            }        }    }} // Function to perform level order traversalvoid levelorder(vector &prev_level){    vector cur_level;    vector print_data;    int l = prev_level.size();         if (l == 0)    {        exit(0);    }         for(int i = 0; i < l; i++)    {        int prev_level_len = prev_level[i]->child.size();                 for(int j = 0; j < prev_level_len; j++)        {                         // enqueue all the children            // into cur_level list            cur_level.push_back(prev_level[i]->child[j]);                         // Copies the entire cur_level            // list into prev_level            print_data.push_back(prev_level[i]->child[j]->val);        }    }         prev_level = cur_level;    for(auto i : print_data)    {        cout << i << " ";    }    levelorder(prev_level);} // Function that calls levelorder method to// perform level order traversalvoid levelorder_root(Node *root){    if (root)    {        vector level;        level.push_back(root);        printf("%d\n", root->val);        levelorder(level);    }} // Driver codeint main(int argc, char const *argv[]){         // -1 is the root element    int arr[] = {-1, -1, -1, -1, -1};    Node *root = new Node(-1);    int l = sizeof(arr) / sizeof(int);    vector que;         // Inserting root element to the queue    que.push_back(-1);         while (true)    {        vector temp;        for(int i = 0; i < l; i++)        {            if (find(que.begin(),                     que.end(), arr[i]) != que.end())            {                // Insert elements into the tree                insert(root, arr[i], new Node(i));                temp.push_back(i);            }        }             // Append child nodes into the queue        // and insert the child        que = temp;                 if (que.size() == 0)        {            break;        }    }    levelorder_root(root);} // This code is contributed by sanjeev2552

Python3

 # Python3 implementation of the approach # Node creationclass Node:     # Constructor    def __init__(self, data):                  self.val = data                 # Since n children are possible for a root.        # A list created to store all the children.        self.child = []    # Function to insertdef insert(root, parent, node):         # Root is empty then the node will become the root    if root is None:        root = node                   else:        if root.val == parent:            root.child.append(node)                    else:             # Recursive approach to            # insert the child            l = len(root.child)                         for i in range(l):                if root.child[i].val == parent:                    insert(root.child[i], parent, node)                else:                    insert(root.child[i], parent, node) # Function that calls levelorder method to# perform level order traversaldef levelorder_root(root):    if root:        level = []        level.append(root)        print(root.val)        levelorder(level) # Function to perform level order traversaldef levelorder(prev_level):     cur_level = []    print_data = []    l = len(prev_level)     if l == 0:        exit()     for i in range(l):           prev_level_len = len(prev_level[i].child)         for j in range(prev_level_len):                         # enqueue all the children            # into cur_level list            cur_level.append(                   prev_level[i].child[j])              # Copies the entire cur_level            # list into prev_level            print_data.append(                   prev_level[i].child[j].val)     prev_level = cur_level[:]                    print(*print_data)    levelorder(prev_level)  # Driver code # -1 is the root element   arr = [-1, -1, -1, -1, -1]root = Node(-1)l = len(arr)que = [] # Inserting root element to the queueque.append(-1) while 1:    temp = []    for i in range(l):        if arr[i] in que:                         # Insert elements into the tree            insert(root, arr[i], Node(i))            temp.append(i)     # Append child nodes into the queue    # and insert the child    que = temp[:]                              if len(que)== 0:        break levelorder_root(root)
Output:
-1
0 1 2 3 4

Time Complexity: O(N^2).
Auxiliary Space: O(N).

My Personal Notes arrow_drop_up