Вопрос обхода дерева Python
мне трудно с пересечением деревьев, и поэтому избегайте его, как чумы... обычно.
у меня есть класс, вроде бы (слегка упрощенная версия здесь, но функционально такая же) как:
class Branch(object):
def __init__(self, title, parent=None):
self.title = title
self.parent = parent
у меня есть словарь из кучи Branch
экземпляры, названия каждого из них в качестве ключей:
tree = {'Foo Branch': foo, 'Sub-Foo Branch': sub_foo, 'Bar Branch': bar}
теперь я знаю, что существуют сложные алгоритмы для эффективного обхода (например, MPTT, et al), особенно для использования с проекты баз данных, где вопросы эффективности наиболее. Я вообще не использую базу данных, только простые объекты в памяти.
учитывая title
of a Branch
, мне нужен list
всех потомков этой ветви (дети, дети детей, так далее) от tree
, так:
- вы все равно рекомендовали бы использовать сложный (для моего мозга без Альго :) алгоритм, такой как MPTT для эффективности в моем случае, или есть простой способ достичь это в одной функции?
- если да, то какую вы бы порекомендовали, зная, что я не использую базу?
- можете ли вы привести пример, или это намного больше, чем я думаю?
Примечание: это не домашнее задание. Я не в школе. Я действительно плохо разбираюсь в алгоритмах. Я использовал Django MPTT для проекта, который требовал деревьев, хранящихся в БД... но все равно не очень хорошо понимаю.
1 ответов
http://en.wikipedia.org/wiki/Depth-first_search
http://en.wikipedia.org/wiki/Tree_traversal
Вы пройти следующим образом в два этапа:
первый проход: Поиск узла запроса с соответствующим ключом. (Этот шаг не нужен, если у вас есть hashmap все узлы во всем дереве; у вас есть это (хорошо), поэтому этот шаг не необходимый.)
второй проход: вызовите модифицированную версию алгоритма на узле запроса, но на этот раз, когда вы посещаете узел, дайте ему (или добавьте его к нелокальной переменной аккумулятора).
однако ваша ситуация немного странная, потому что обычно деревья имеют указатели на детей, а также, вроде как список с двойной связью. К сожалению, у нас нет такой информации... но, к счастью, легко добавить, что информация:
nodes = tree.values()
for node in nodes:
if node.parent:
if not hasattr(node.parent, 'children'):
node.parent.children = []
node.parent.children +=[ node ]
теперь мы можем продолжить наш пример:
def traverse(root, callback):
"""
Peform callback on all nodes in depth-first order
e.g. traverse(root, lambda x:print(x))
"""
yield root, callback(root)
for child in root.children:
traverse(child)
def getAllDescendents(title):
queryNode = titlesToNodes[title] #what you call 'tree'
for node,blah in traverse(queryNode, lambda x:None):
yield node