Вывести все возможные пути в двоичном дереве - PullRequest
0 голосов
/ 19 мая 2018

Я пытаюсь распечатать все возможные пути в двоичном дереве.Я могу напечатать все пути от корня к листу, но не могу понять, как добавить пути от листа к листу. (Я использую обход предзаказа для корня к листу).Итак, в основном:

Если мое дерево

       6
     /    \
    4      0
   / \      \
  1   3      1

Если хотите, чтобы код печатал все пути:

6,4,1
6,4,3
6,0,1
1,4,6,0,1
3,4,6,0,1 
1,4,3  
4,6,0  
4,6,0,1  
etc.

Может кто-нибудь, пожалуйста, помогите мне с этимбинарное дерево?Я был бы очень признателен за вашу помощь, поскольку я новичок в этом обществе и в Python / Java.

Спасибо

1 Ответ

0 голосов
/ 19 мая 2018

Одно примечательное свойство деревьев заключается в том, что для каждой комбинации узла (x, y) существует уникальный неповторяющийся путь от x до y.В частности, этот путь можно найти, найдя первого общего предка z из x и y и выбрав путь x -> z + z -> y.

Таким образом, алгоритм для поиска всего пути может выглядеть следующим образомthis

for each pair of distinct nodes x, y in the tree:
    find all common ancestors of x and y
    let z be the lowest common acestor in the tree
    let p be the path from x to z
    append the path from z to y to p, excluding the duplicate z
    print p

Вот объектно-ориентированный подход, который реализует необходимый метод для достижения вышеупомянутого.

class Tree:
    def __init__(self, value, left=None, right=None):
        self.value = value
        self.left = left
        self.right = right
        self.parent = None

        if left is not None:
            left.parent = self

        if right is not None:
            right.parent = self

    def __iter__(self):
        """Return a left-to-right iterator on the tree"""
        if self.left:
            yield from iter(self.left)
        yield self
        if self.right:
            yield from iter(self.right)

    def __repr__(self):
        return str(self.value)

    def get_ancestors(self):
        """Return a list of all ancestors including itself"""
        ancestors = {self}
        parent = self.parent
        while parent:
            ancestors.add(parent)
            parent = parent.parent

        return ancestors

    def get_path_to_ancestor(self, ancestor):
        """
        Return the path from self to ancestor as a list
        output format: [self, ..., ancestor]
        """
        path = []
        parent = self
        try:
            while True:
                path.append(parent)
                if parent is ancestor:
                    break
                else:
                    parent = parent.parent
        except AttributeError:
            return None

        return path

    def get_path_to(self, other):
        """
        Return the path from self to other as a list
        output format: [self, ..., first common acestor, ..., other]
        """
        common_ancestors = self.get_ancestors() & other.get_ancestors()
        first_common_ancestor = {
            a for a in common_ancestors
            if a.left not in common_ancestors and a.right not in common_ancestors
        }.pop()

        return self.get_path_to_ancestor(first_common_ancestor)\
               + list(reversed(other.get_path_to_ancestor(first_common_ancestor)))[1:]

Вот как он применяется к дереву, которое вы предоставили в качестве примера.

tree = Tree(
    6,
    Tree(4,
         Tree(1),
         Tree(3)),
    Tree(0,
         Tree(1)))

nodes = list(tree)

for i in range(len(nodes)):
    for j in range(i + 1, len(nodes)):
        print([t for t in nodes[i].get_path_to(nodes[j])])

Вот все пути, которые печатаются.

[1, 4]
[1, 4, 3]
[1, 4, 6]
[1, 4, 6, 0, 1]
[1, 4, 6, 0]
[4, 3]
[4, 6]
[4, 6, 0, 1]
[4, 6, 0]
[3, 4, 6]
[3, 4, 6, 0, 1]
[3, 4, 6, 0]
[6, 0, 1]
[6, 0]
[1, 0]
...