pythonpython-3.xsearchsearch-tree

Tree Search - given two nodes in a tree, check if they are connected - python


Given a search tree, e.g.

"1"
 └ "2"
    ├ "2.1"
    ┊   └ "3"
    ┊
    └ "2.2"
        └ "2.2.1"
             └ "3"

As well as two nodes, a and b, that belong on that tree, e.g. "2.1" and "3". How can we check whether a and b are parent-child (or child-parent) related / connected?

For the first example, True should be yielded. Here are some more:

a="3"      b="1"    -> False
a="3"      b="2"    -> False
a="2.2.1"  b="2.2"  -> True
a="2.2.1"  b="3"    -> True

I'm currently using the anytree library, with which I am struggling to implement this solution. The above graph is a structural simplification. What I have currently tried implementing is outlined here: https://pastebin.com/Mjk7gyqH

If the answer could be given with either pure python or anytree, that would be fantastic, but any answer is better than none.


Solution

  • You can use simple recursion:

    tree = {'name': '1', 'children': [{'name': '2', 'children': [{'name': '2.1', 'children': [{'name': '3'}]}, {'name': '2.2', 'children': [{'name': '2.2.1', 'children': [{'name': '3'}]}]}]}]}
    def in_tree(d, node):
       return d['name'] == node or any(in_tree(i, node) for i in d.get('children', []))
    
    def lookup(tree, a, b, flag=False):
       if tree['name'] == b and flag:
         return True
       return any(lookup(j, a, b, tree['name'] == a) for j in tree.get('children', []))
    
    test = [['3', '1'], ['3', '2'], ['2.2.1', '2.2'], ['2.2.1', '3'], ['60', '70']]
    for a, b in test:
       if not in_tree(tree, a) or not in_tree(tree, b):
          raise AttributeError('Node(s) missing in tree')
       print(any([lookup(tree, a, b), lookup(tree, b, a)]))
    

    Output:

    False
    False
    True
    True
    Traceback (most recent call last):
      File "<stdin>", line 3, in <module>
    AttributeError: Node(s) missing in tree