Menu
Coddy logo textTech

Двоичное дерево

Последнее обновление

Двоичное дерево — это иерархия, в которой каждый узел имеет не более двух потомков, называемых левым и правым потомком. Верхний узел — корень, узлы без потомков — листья, а число рёбер от корня до самого глубокого листа — это высота дерева. В отличие от двоичного дерева поиска, у обычного двоичного дерева нет правила упорядочивания — это только форма. Нажмите «воспроизвести» выше, чтобы увидеть, как дерево заполняется уровень за уровнем, а затем обходится симметрично (левый, узел, правый).

Двоичные деревья лежат в основе многих структур — двоичных деревьев поиска, куч, деревьев выражений и других. Обходы посещают каждый узел в определённом порядке: симметричный (in-order), прямой (pre-order) и обратный (post-order) — это три обхода в глубину, каждый полезен для своих задач.

Терминология

ТерминЗначение
КореньВерхний узел, без родителя
ЛистУзел без потомков
ВысотаСамый длинный путь от корня до листа (в рёбрах)
ГлубинаРасстояние узла от корня
ПолноеВсе уровни заполнены, кроме, возможно, последнего, который заполняется слева направо

Три обхода в глубину

ОбходПорядокТипичное применение
Симметричный (in-order)Левый, узел, правыйОтсортированный вывод BST
Прямой (pre-order)Узел, левый, правыйКопирование / сериализация дерева
Обратный (post-order)Левый, правый, узелУдаление / вычисление дерева

Разобранный пример

Симметричный обход дерева, построенного из [4, 2, 6, 1, 3, 5] (заполненного уровень за уровнем):

ШагВ узлеДействие
14Рекурсия в левое поддерево 4 до его посещения
22Рекурсия в левое поддерево 2 до его посещения
31Лист, нет левого потомка: посещаем 1, вывод [1]
42Левое завершено: посещаем 2, вывод [1, 2], затем рекурсия вправо
53Лист: посещаем 3, вывод [1, 2, 3]
64Левое поддерево завершено: посещаем 4, вывод [1, 2, 3, 4], затем рекурсия вправо
75Левый потомок 6, лист: посещаем 5, вывод [1, 2, 3, 4, 5]
86Левое завершено, нет правого потомка: посещаем 6, вывод [1, 2, 3, 4, 5, 6]

Когда использовать двоичное дерево

Используйте, когдаИзбегайте, когда
Нужно моделировать по своей природе иерархические данные (файловые системы, деревья выражений, DOM)Данные плоские и подошёл бы список или массив — дерево лишь добавляет накладные расходы
Нужны упорядоченные операции и вы можете держать его сбалансированным (BST или самобалансирующееся дерево)Нужен поиск по ключу за среднее O(1) — хеш-таблица превосходит любое дерево
Нужно обрабатывать структурированные данные в симметричном, прямом или обратном порядкеУзлы вставляются в отсортированном порядке в несбалансированный BST — он вырождается в список O(n)
Важны запросы по диапазону или упорядоченный обход, чего хеш-таблицы не даютПамять ограничена — каждый узел несёт два указателя на потомков помимо полезных данных

Код Binary Tree

Чистая, готовая к запуску реализация Binary Tree на Python, JavaScript, Java, C++, C. Выберите язык, скопируйте код или откройте его уже загруженным в плейграунде Coddy.

Код Binary Tree на Python

Python
1from collections import deque2
3
4class Node:5    def __init__(self, value):6        self.value = value7        self.left = None8        self.right = None9
10
11def insert(root, value):12    # Level-order insert: fill the first empty child slot found13    if root is None:14        return Node(value)15    queue = deque([root])16    while queue:17        node = queue.popleft()18        if node.left is None:19            node.left = Node(value)20            return root21        queue.append(node.left)22        if node.right is None:23            node.right = Node(value)24            return root25        queue.append(node.right)26
27
28def inorder(node):29    if node is None:30        return []31    return inorder(node.left) + [node.value] + inorder(node.right)32
33
34root = None35for value in [1, 2, 3, 4, 5, 6, 7]:36    root = insert(root, value)37
38print("Root:   ", root.value)39print("Inorder:", inorder(root))
Запустите этот код в плейграунде Python

Часто задаваемые вопросы о двоичных деревьях

В чём разница между двоичным деревом и двоичным деревом поиска?
Двоичное дерево просто ограничивает каждый узел не более чем двумя потомками, без всякого упорядочивания. Двоичное дерево поиска добавляет правило, что всё в левом поддереве меньше, а всё в правом поддереве больше, что и делает поиск быстрым.
Что такое симметричный (in-order) обход?
Симметричный обход рекурсивно посещает левое поддерево, затем узел, затем правое поддерево. Для двоичного дерева поиска это даёт значения в порядке возрастания, поэтому это самый распространённый обход для демонстрации.
Что такое полное двоичное дерево?
У полного двоичного дерева все уровни полностью заполнены, кроме, возможно, последнего, который заполняется слева направо. Такая форма позволяет компактно хранить дерево в массиве (без указателей на потомков), именно так реализуются двоичные кучи.
Когда стоит использовать двоичное дерево вместо массива или хеш-таблицы?
Обращайтесь к дереву, когда ваши данные естественно иерархичны или когда нужны упорядоченные операции вроде запросов по диапазону и отсортированного обхода, чего хеш-таблицы предложить не могут. Если нужен только быстрый поиск по ключу без упорядочивания, среднее O(1) обращение хеш-таблицы превосходит дерево, а для плоских данных массив проще и лучше работает с кешем.
В чём разница между высотой и глубиной двоичного дерева?
Глубина измеряется от корня вниз до конкретного узла: число рёбер на пути от корня до этого узла. Высота измеряется от узла вниз до его самого глубокого листа, поэтому высота всего дерева — это глубина его самого глубокого узла. Дерево из одного узла имеет высоту 0, и его единственный узел также имеет глубину 0.
Почему несбалансированное двоичное дерево работает так плохо?
Поиск, вставка и удаление в двоичном дереве поиска стоят O(h), где h — высота. Когда ключи вставляются в отсортированном порядке, дерево превращается в прямую линию, поэтому h растёт до n, и каждая операция вырождается в O(n) — не лучше связного списка. Самобалансирующиеся деревья, такие как AVL или красно-чёрные, удерживают высоту на уровне O(log n), чтобы этого избежать.
Coddy programming languages illustration

Освойте алгоритмы с Coddy

НАЧАТЬ