Depth of an N-Ary tree and Finding Route to a node in an N-Ary tree

0 / 263
Depth Route Node N-Ary Tree

Depth of an N-Ary tree and Finding Route to a node in an N-Ary tree

 

Problem Statement:- Given an N-Ary tree, how to find it’s depth and trace route to a destination from a source node of the tree.

 

Consider the below N-Ary tree. In this example, we have used JSON object which contains all the hierarchical representations of an N-Ary tree and thus the traversing algorithm and route tracing algorithms are according to the JSON structure.

 

DEMO here:- Give it a go

 

 

The JSON that represents this tree is :-

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
[{
    head: '1',
    id: 'aa',
    contents: 'Node1',
    children: [
        {
            head: '2',
            id: 'a1',
            contents: 'Node1-Child',
            children: [
                { head: '2.3', id: 'a11', contents: 'Node1.1-Child', children:[{ head: '2.4', id: 'a12', contents: 'Node1.2-Child' },
                  { head: '2.5', id: 'a13', contents: 'Node1.3-Child' }] }
                 
            ]
        },
        {
            head: '3',
            id: 'a3',
            contents: 'Node1-Child',
            children: [
                { head: '3.3', id: 'a121', contents: 'Node3.1-Child', children:[{ head: '3.4', id: 'a122', contents: 'Node3.2-Child' },
                  { head: '3.5', id: 'a133', contents: 'Node3.3-Child' }] }
            ]
        },
        {
            head: '4',
            id: 'a2',
            contents: 'Node1.2-Child',
            children: [
                { head: '5', id: 'a21', contents: 'Node1.2.1-Child', children:[{head: '5.1', id: 'a245', contents: 'Node1.2.1.1-Child'}]},
                { head: '6', id: 'a22', contents: 'Node1.2.2-Child',  children:[{head: '6.1', id: 'a2454', contents: 'Node1.2.1.2-Child',
                children:[{head: '6.2', id: 'a24445', contents: 'Node1.2.1.4-Child',
                children:[{ head: '6.3', id: 'a1341', contents: 'Node6.2-Child'}]},
                ]}]}
            ]
        }
    ]
}];

 

Algorithm for finding depth of tree:

 

1. Loop through the JSON array and check each Key:Value pair for data type array/object.

 

2. Recursively invoke the JSON traversing till the last item of JSON array is reached for each such child array obtained in Step 1. Each child array here represents a level of N-Ary tree. Store the levels here for each such child array which represents children of a parent node at a level N.

 

3.For each JSON object, iterate through the JSON key attributes and recursively invoke JSON traversing for each property in JSON child object be it of type array or object.

 

4.Once there are no more arrays in Step 2 and no objects/arrays within the parent JSON object, increment the height obtained from step 2 by 1 for accommodating the root of the tree and return it and exit.

 

Below is the JS code for this algorithm:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
function calcHeight(theObject, height) {
    if (theObject instanceof Array) {
        for (var i = 0; i < theObject.length; i++) {
            //console.log("Node = ", theObject[i].head, "Node Level = ", height);
            heightOfTree = height;
            calcHeight(theObject[i], height);
        }
    } else {
        for (var prop in theObject) {
            if (theObject[prop] instanceof Object || theObject[prop] instanceof Array) {
                calcHeight(theObject[prop], ++height);
            }
        }
    }
    return heightOfTree + 1;
}

 

Algorithm for tracing route to destination from source node:
 

1. This reuses the previous algorithm logic to a large extent. Using previous algorithm, obtain a map of Node and the level at which the Node is based.
2. Use the NodeMap from step 1 to find the destination node in the map and save its level.

 

3. Iterate backwards, through NodeMap again from the index where destination is found. Keep decrementing by one and collect all nodes where the levels are in descending order.

 

4. Repeat step 3 until root node and slice the collection until destination node by looking up source node in the path obtained as a result of step 3 and 4. Return the sliced collection which will have the path from source to destination in case, if they are directly connected.

 

5. If there is no direct connectivity between source and destination , then trace route from source till the root and from root till destination and concatenate the results. If there are repeating nodes in this path, get rid of duplicate such nodes and return the final result. If that’s not the case, return concatenated results as is.

 

Below is the Algorithm for extracting shortest path from a given path

 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
function findShortestPath(path) {
    var index1, index2, arr1, arr2;
    for (i = path.length - 1; i >= 0; i--) {
        for (j = i - 1; j >= 0; j--) {
            if (path[i] === path[j]) {
                index1 = i;
                index2 = j;
                arr1 = path.slice().slice(0, index2);
                arr2 = path.slice().slice(index1, path.length);
                return arr1.concat(arr2);
            }
        }
    }
    return null;
}

 

JS code for the above algorithm is as below:-

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
function getRoute() {
    var source = document.getElementById("source").value,
        destination = document.getElementById("destination").value;
    var path = traceRoute(source, destination);

    if (path instanceof Array) {
        document.getElementById("route").innerHTML = "<h2>Route from Nodes : " + source + " to " + destination + " is : <br />" + path.join("->") + "</h2>";
    } else if (path === -1) {
        document.getElementById("route").innerHTML = "<h2>Invalid Input : Either of the Nodes, " + source + " or " + destination +
            " you entered doesn't exist in the tree!!</h2>";
    } else {
        document.getElementById("route").innerHTML = "<h2>Node " + destination + " isn't reachable from Node " + source + "</h2>";
    }
}

function traceRoute(source, destination) {
    var routes = findRoute(jsonObject, 0),
        pivot = -1,
        spivot = -1;
    for (var index = 0; index < routes.length; index++) {
        if (destination === routes[index].node) {
            pivot = index;
        }
        if (source === routes[index].node) {
            spivot = index;
        }
    }

    if (pivot === -1 || spivot === -1) {
        return -1;
    }

    var path = routes[pivot].node;
    var level = routes[pivot].level;


    while (pivot > 0) {
        pivot--;
        if (level - routes[pivot].level === 1) {
            path += "|" + routes[pivot].node;
            level = routes[pivot].level;
        }
    }

    var routeArr = path.split("|").reverse();
    if (routeArr.some(function(item, index) {
            if (item === source) {
                routeArr = routeArr.splice(routeArr.indexOf(source), routeArr.length);
                return true;
            }
        })) {
        return routeArr;
    } else {
        // try finding shortest path first if it exists
        //var finalRoute = findShortestPath(source, destination);
        // else try again here as nodes could be reachable via root and shortest path is not found
        var route1 = traceRoute(routeMap[0].node, source).reverse();
        var arr = traceRoute(routeMap[0].node, destination);
        var route2 = (routeMap[0].node === destination) ? [] : arr.slice(1, arr.length);
        var finalPath = route1.concat(route2);
        var shortestPath = findShortestPath(finalPath);
        if (shortestPath) {
            return shortestPath;
        } else {
            return route1.concat(route2);
        }
    }
}



function findRoute(theObject, height) {
    if (theObject instanceof Array) {
        for (var i = 0; i < theObject.length; i++) {
            console.log("Node = ", theObject[i].head, "Node Level = ", height);
            var object = {
                "node": theObject[i].head,
                "level": height
            };

            routeMap.push(object);
            findRoute(theObject[i], height);
        }
    } else {
        for (var prop in theObject) {
            if (theObject[prop] instanceof Object || theObject[prop] instanceof Array) {
                findRoute(theObject[prop], ++height);
            }
        }
    }
    return routeMap;
}

 

 

Hope you enjoyed reading this. Like us on Golibrary for interesting reads like this.

 

 

Comments

comments


An avid reader, responsible for generating creative content ideas for golibrary.co. His interests include algorithms and programming languages. Blogging is a hobby and passion.

Related Posts