Python, возвращающий список из рекурсивного метода

Я использую двоичное дерево, описанное в этой книге, решение проблем с помощью алгоритмов и структур данных

class BinaryTree:
    def __init__(self,rootObj):
        self.key = rootObj
        self.leftChild = None
        self.rightChild = None

Уже существует метод обхода предварительного заказа, определенный следующим образом.

def preorder(tree):
    if tree:
        print(tree.self.key)
        preorder(tree.getLeftChild())
        preorder(tree.getRightChild())

Я просто хочу добавить возвращаемое значение в список посещенных узлов. Так что я могу сделать что-то вроде

for i in preorder(tree):
    etc...

У меня проблемы с возвратом списка из рекурсивного метода. Рекурсия останавливается, как только она достигает "возврата", я попробовал варианты, используя

return [tree.self.key] + preorder()

Или же

yield ...

Есть идеи?

4 ответа

Ты уверен что хочешь tree.self.key а не просто tree.key когда вы печатаете?

В противном случае решение с yield from (Python 3.3+):

def preorder(tree):
    if tree:
        yield tree
        yield from preorder(tree.getLeftChild())
        yield from preorder(tree.getRightChild())

Или с простым yield:

def preorder(tree):
    if tree:
        yield tree
        for e in preorder(tree.getLeftChild()):
            yield e
        for e in preorder(tree.getRightChild()):
            yield e

Обратите внимание, что с помощью yield или же yield from превращает функцию в функцию генератора; в частности, если вам нужен фактический список (например, для индексации, нарезки или отображения), вам нужно явно создать его: list(preorder(tree)),

Если у вас разное количество детей, его легко адаптировать:

def preorder(tree):
    if tree:
        yield tree
        for child in tree.children:
            yield from preorder(child)

Вы должны фактически вернуть значение из рекурсивной функции (в настоящее время это просто печать значений). И вы должны построить список по ходу дела, и, возможно, немного очистить код - что-то вроде этого:

def preorder(tree):
    if not tree:
        return []
    # optionally, you can print the key in this line: print(self.key)
    return [tree.key] + preorder(tree.leftChild) + preorder(tree.rightChild)

Вы можете добавить второй аргумент preorder функция, что-то вроде

def preorder(tree, visnodes):
    if tree:
        visnodes.append(tree.self.key)
        print(tree.self.key)
        preorder(tree.getLeftChild(), visnodes)
        preorder(tree.getRightChild(), visnodes)

...
vn = []
preorder(tree, vn)

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

def preorder(tree):
        if tree:
            return ([tree.key] + preorder(tree.getLeftChild()) +
                    preorder(tree.getRightChild()))
        return []

Для n-арного дерева:

def preorder(tree):
    if tree:
        lst = [tree.key]
        for child in tree.children:
            lst.extend(preorder(child))
        return lst
    return []
Другие вопросы по тегам