Обход бинарного дерева с использованием итерации вместо рекурсии в Python - PullRequest
3 голосов
/ 07 апреля 2020

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

class Node:
    def new(rep):
        if type(rep) is list:
            left = Node.new(rep[0])
            right = Node.new(rep[1])
            return Internal(left, right)
        else:
            return Leaf(rep)


class Leaf(Node):
    def __init__(self, val):
        self.val = val

    def sum_leaves(self, sum):
        return sum + self.val


class Internal(Node):
    def __init__(self, left, right):
        self.left = left
        self.right = right

    def sum_leaves(self, sum):
        return self.right.sum_leaves(self.left.sum_leaves(sum))


class Tree:
    def __init__(self, rep):
        self.root = Node.new(rep)

    # Traverse the tree and return the sum of all leaves
    def sum_leaves(self):
        return self.root.sum_leaves(0)


treerep = [[3, [5, -1]], [[1, 7], [2, [3, [11, -9]]]]]
tree = Tree(treerep)
print(tree.sum_leaves())

В этом случае вывод:

22

Как я могу использовать итерацию вместо рекурсии для sum_leaves метода?

Ответы [ 2 ]

3 голосов
/ 07 апреля 2020

Вы можете использовать Поиск в глубину, который использует некоторое время l oop:

class Tree:
    def __init__(self, rep):
        self.root = Node.new(rep)

    def sum_dfs(self):

        sum = 0
        stack = [self.root]

        while len(stack):

            node = stack.pop()

            if isinstance(node, Internal):
                stack.append(node.left)
                stack.append(node.right)

            elif isinstance(node, Leaf):
                sum += node.val

        return sum
0 голосов
/ 11 апреля 2020

Объект deque из коллекций очень эффективен для реализации «ручного» стека и может помочь с этим видом обхода. Я бы предложил определить метод итератора, который будет проходить по иерархии, используя al oop (и deque), а затем использовать этот метод для реализации метода sum_leaves ().

from collections import deque

def traverse(self,condition=None): # on the Node class
    nodes = deque([self])
    while nodes:
        node = nodes.popleft()
        if not condition or condition(node): yield node
        if node.isLeaf: continue
        if node.left:  nodes.append(node.left)
        if node.right: nodes.append(node.right)

@property
def isLeaf(self): isinstance(self,Leaf)  # on the Node class

def sum_leaves(self): # on the Node class
    return sum(n.val for n in self.traverse(lambda n:n.isLeaf))

def sum_leaves(self): # on the Tree class
    return self.root.sum_leaves()

Я считаю, что было бы намного меньше исключений в коде, если бы вы не разделяли древовидную структуру на 3 несовместимых класса. Все узлы (включая дерево, которое само должно быть root) должны иметь свойство left, right и value (по крайней мере, на уровне подписи).

...