Efficient unidirectional tree movement

I have a unidirectional tree of objects in which each object points to a parent. Given an object, I need to get all its subtree of descendants, as a set of objects. Objects are not actually in any data structure, but I can easily get a collection of all objects.

A naive approach is to examine each object in a batch, to see if a given object is an ancestor and does not leave it aside. That would not be too effective ... It carries the overhead O (N * N), where N is the number of objects.

Another approach is recursive, that is, searching for objects of direct children and repeating the process for the next level. Unfortunately, the tree is unidirectional ... there is no direct approach to children, and it will only be slightly cheaper than the previous approach.

My question is: is there an efficient algorithm I'm looking at here?

Thank,

Yuval = 8 -)

+3
source share
4 answers

As already mentioned, build a hash table / map of objects into a list of your (direct) child elements.

From there, you can easily find the list of direct children of your “target”, and then repeat the process for each object in the list.

Here's how I did it in Java and used generics, with a queue instead of any recursion:

public static Set<Node> findDescendants(List<Node> allNodes, Node thisNode) {

    // keep a map of Nodes to a List of that Node direct children
    Map<Node, List<Node>> map = new HashMap<Node, List<Node>>();

    // populate the map - this is O(n) since we examine each and every node
    // in the list
    for (Node n : allNodes) {

        Node parent = n.getParent();
        if (parent != null) {

            List<Node> children = map.get(parent);
            if (children == null) {
                // instantiate list
                children = new ArrayList<Node>();
                map.put(parent, children);
            }
            children.add(n);
        }
    }


    // now, create a collection of thisNode children (of all levels)
    Set<Node> allChildren = new HashSet<Node>();

    // keep a "queue" of nodes to look at
    List<Node> nodesToExamine = new ArrayList<Node>();
    nodesToExamine.add(thisNode);

    while (nodesToExamine.isEmpty() == false) {
        // pop a node off the queue
        Node node = nodesToExamine.remove(0);

        List<Node> children = map.get(node);
        if (children != null) {
            for (Node c : children) {
                allChildren.add(c);
                nodesToExamine.add(c);
            }
        }
    }

    return allChildren;
}

- - O (n) O (2n), , . node , , node - ( node), node .

+2

, , . -, -. O (n). - .

+3

, ( , mysql) . , ( ).

. , , . , , - .

0

, , , , . . O (n ^ 2).

, -. - (O (1) O (n)).

0

Source: https://habr.com/ru/post/1698358/


All Articles