Бинарное дерево (двоичное дерево) — это дерево, в котором каждая вершина имеет не более двух детей, называемых левым и правым потомками.
Формально, бинарное дерево — это либо пустое дерево, либо тройка $(r, L, R)$, где $r$ — корень, $L$ — левое поддерево (бинарное дерево), $R$ — правое поддерево (бинарное дерево).
Бинарное дерево отличается от общего дерева тем, что:
Каждый узел имеет не более двух детей
Дети различаются: левый и правый потомки — разные позиции
Порядок детей важен: дерево с левым ребёнком $A$ и правым $B$ отличается от дерева с левым $B$ и правым $A$
Основные понятия
Определение
Корень — единственная вершина без родителя.
Лист — вершина без детей.
Внутренняя вершина — вершина, не являющаяся листом.
Глубина вершины — длина пути от корня до этой вершины (количество рёбер).
Высота вершины — длина самого длинного пути от этой вершины до листа.
Высота дерева — высота корня (максимальная глубина среди всех вершин).
Уровень — множество вершин с одинаковой глубиной.
Определение
Полное бинарное дерево уровня $h$ — это бинарное дерево, в котором все уровни от $0$ до $h$ заполнены полностью (каждая внутренняя вершина имеет ровно двух детей, и все листья находятся на уровне $h$).
Свойства бинарных деревьев
Теорема
В бинарном дереве на уровне $i$ находится не более $2^i$ вершин.
Доказательство
Доказательство по индукции по $i$.
База: $i = 0$. На уровне $0$ находится только корень — одна вершина. $2^0 = 1$. Верно.
Переход: пусть на уровне $i$ находится не более $2^i$ вершин. Каждая вершина уровня $i$ имеет не более двух детей. Значит, на уровне $i+1$ находится не более $2 \cdot 2^i = 2^{i+1}$ вершин.
Теорема
В бинарном дереве высоты $h$ находится не более $2^{h+1} - 1$ вершин.
Доказательство
Суммируем максимальное количество вершин на каждом уровне:
$$
\sum_{i=0}^{h} 2^i = 2^{h+1} - 1
$$
по формуле суммы геометрической прогрессии.
Следствие
Бинарное дерево с $n$ вершинами имеет высоту не менее $\lfloor \log_2 n \rfloor$.
Доказательство
Из предыдущей теоремы: $n \leqslant 2^{h+1} - 1$, откуда $h \geqslant \log_2(n+1) - 1 = \log_2 \frac{n+1}{2}$.
Более точная оценка: $h \geqslant \lfloor \log_2 n \rfloor$.
Теорема
В бинарном дереве с $n$ вершинами количество листьев не менее $\lceil n/2 \rceil$ в дереве максимальной высоты и не более $n$ (тривиально) в дереве минимальной высоты. Для полного бинарного дерева количество листьев равно $2^h$, где $h$ — высота дерева.
Лемма
В полном бинарном дереве с $n$ вершинами высота равна $\lfloor \log_2 n \rfloor$.
Доказательство
Для полного бинарного дерева высоты $h$:
$$
2^h \leqslant n < 2^{h+1}
$$
Откуда $h \leqslant \log_2 n < h + 1$, то есть $h = \lfloor \log_2 n \rfloor$.
Типы бинарных деревьев
Полное бинарное дерево
Определение
Полное бинарное дерево — бинарное дерево, в котором все уровни полностью заполнены, кроме возможно последнего, причём последний уровень заполнен слева направо без пропусков.
Полное бинарное дерево:
1
/ \
2 3
/ \ /
4 5 6
Полные бинарные деревья удобно представлять массивом (как в двоичной куче).
classArrayBinaryTree:
def__init__(self):
self.tree = []
defroot(self):
return0if self.tree else-1defleft_child(self, i):
left =2* i +1return left if left < len(self.tree) else-1defright_child(self, i):
right =2* i +2return right if right < len(self.tree) else-1defparent(self, i):
return (i -1) //2if i >0else-1defvalue(self, i):
return self.tree[i] if0<= i < len(self.tree) elseNonedefappend(self, value):
self.tree.append(value)
# Создание дерева:# 1# / \# 2 3# / \# 4 5tree = ArrayBinaryTree()
for val in [1, 2, 3, 4, 5]:
tree.append(val)
print(tree.value(tree.left_child(0))) # 2print(tree.value(tree.right_child(0))) # 3
#include<vector>#include<iostream>classArrayBinaryTree {
private: std::vector<int> tree;
public:int root() const {
return tree.empty() ?-1:0;
}
intleftChild(int i) const {
int left =2* i +1;
return left < tree.size() ? left : -1;
}
intrightChild(int i) const {
int right =2* i +2;
return right < tree.size() ? right : -1;
}
intparent(int i) const {
return i >0? (i -1) /2:-1;
}
intvalue(int i) const {
return (i >=0&& i < tree.size()) ? tree[i] :-1;
}
voidappend(int val) {
tree.push_back(val);
}
};
intmain() {
ArrayBinaryTree tree;
for (int val : {1, 2, 3, 4, 5}) {
tree.append(val);
}
std::cout << tree.value(tree.leftChild(0)) << std::endl; // 2
std::cout << tree.value(tree.rightChild(0)) << std::endl; // 3
return0;
}
Массивное представление эффективно для полных деревьев, но может приводить к большому расходу памяти для разреженных деревьев.
Количество бинарных деревьев
Теорема
Количество различных бинарных деревьев с $n$ вершинами равно $C_n$ — $n$-му числу Каталана:
$$
>C_n = \frac{1}{n+1} \binom{2n}{n}
>$$
Доказательство
Пусть $T_n$ — количество бинарных деревьев с $n$ вершинами.
База: $T_0 = 1$ (пустое дерево).
Рекуррентное соотношение: Для дерева с $n$ вершинами корень занимает одну вершину. Если в левом поддереве $k$ вершин, то в правом — $n - 1 - k$ вершин. Суммируя по всем возможным $k$:
$$
T_n = \sum_{k=0}^{n-1} T_k \cdot T_{n-1-k}
$$
Это рекуррентное соотношение для чисел Каталана. Решение даёт формулу:
$$
T_n = C_n = \frac{1}{n+1} \binom{2n}{n}
$$
Числа Каталана растут экспоненциально: $C_n \approx \frac{4^n}{n^{3/2}\sqrt{\pi}}$.