Класс подключенных узлов на основе
A Node
является стандартным подходом.Это может быть трудно визуализировать.
По мотивам эссе на Шаблоны Python - Реализация графиков , рассмотрим простой словарь:
Дано
Двоичное дерево
a
/ \
b c
/ \ \
d e f
Код
Создать словарь из уникальных узлов:
tree = {
"a": ["b", "c"],
"b": ["d", "e"],
"c": [None, "f"],
"d": [None, None],
"e": [None, None],
"f": [None, None],
}
Подробности
- Каждая пара ключ-значение представляет собой уникальный узел , указывающий на его дочерние элементы.
- Список (или кортеж) содержит упорядоченную пару левых / правых дочерних элементов.
- С диктовкой , имеющей упорядоченную вставку , предположим, что первая запись является корнем.
- Обычными методами могут быть функции, которые изменяют или пересекают диктовку (см.
find_all_paths()
).
Древовидные функции часто включают следующие общие операции:
- traverse : вывод каждого узла в заданном порядке (обычно слева насправа)
- поиск в ширину (BFS): уровни перемещения
- поиск в глубину (DFS): сначала переходы по ветвям (до / в / после заказа)
- insert : добавить узел в дерево в зависимости от количества дочерних элементов
- remove : удалить узел в зависимости от количествадети
- обновление : объединить отсутствующие узлы из одного дерева в другое
- посещение : получить значение пройденного узла
Попробуйте реализовать все эти операции.Здесь мы демонстрируем одну этих функций - обход BFS:
Пример
import collections as ct
def traverse(tree):
"""Yield nodes from a tree via BFS."""
q = ct.deque() # 1
root = next(iter(tree)) # 2
q.append(root)
while q:
node = q.popleft()
children = filter(None, tree.get(node))
for n in children: # 3
q.append(n)
yield node
list(traverse(tree))
# ['a', 'b', 'c', 'd', 'e', 'f']
This алгоритм поиска в ширину * (порядок уровней) , применяемый к узлу узлов и дочерних элементов.
- Инициализировать очередь FIFO .Мы используем
deque
, но queue
или list
работает (последний неэффективен). - Получить и поставить в очередь корневой узел (предполагает, что корень является первой записью в dict, Python 3.6 +).
- Итеративно удаляет очередь из узла, ставит в очередь его дочерние элементы и выдает значение узла.
См. также этотглубина учебник на деревьях.
Insight
Что-то замечательное в обходах вообще, мы можем легко изменить последний итерационный подход к поиск в глубину (DFS) , просто заменив очередь на стек (он же LIFO Queue).Это просто означает, что мы снимаем с той же стороны, что ставим в очередь.DFS позволяет нам искать каждую ветвь.
Как?Поскольку мы используем deque
, мы можем эмулировать стек, изменив node = q.popleft()
на node = q.pop()
(справа).В результате получается правый, предзаказ DFS : ['a', 'c', 'f', 'b', 'e', 'd']
.