EssayAI
Блог
Блог
Математика и алгоритмы

Высота и глубина дерева: формулы и примеры

11 июня 2026Время чтения: 8 минут
#высота дерева#глубина дерева#двоичное дерево#структуры данных#алгоритмы

Высота и глубина дерева -- базовые характеристики древовидных структур данных: без них не обходится ни анализ алгоритмов обхода, ни оценка эффективности двоичного поиска, ни понимание балансировки. На практике многие студенты путают эти два термина, потому что оба описывают «расстояние» в дереве, но считаются в разных направлениях. Ниже разберём точные определения, выведем формулы для полного двоичного и вырожденного дерева, разберём типовые задачи. Начните с интерактивного калькулятора: задайте число уровней, выберите тип дерева и посмотрите, как меняются высота и глубина каждого уровня.

Определения: высота и глубина

Глубина узла d(v)d(v) -- это длина пути от корня до узла vv, то есть количество рёбер на этом пути. У корня глубина равна нулю: d(root)=0d(\text{root}) = 0. У детей корня d=1d = 1, у их детей d=2d = 2 и так далее. Формально:

d(v)=число рёбер на пути от корня до v.d(v) = \text{число рёбер на пути от корня до } v.

Высота узла h(v)h(v) -- длина наидлиннейшего пути от узла vv вниз до листа:

h(v)=maxlleaves(v)d(l,v),h(v) = \max_{l \in \text{leaves}(v)} d(l, v),

где d(l,v)d(l, v) -- расстояние от vv до листа ll в поддереве под vv. У листа высота равна нулю: h(leaf)=0h(\text{leaf}) = 0.

Высота дерева HH -- это высота корня:

H=h(root)=maxlleavesd(root,l).H = h(\text{root}) = \max_{l \in \text{leaves}} d(\text{root}, l).

Иными словами, высота дерева -- длина наидлиннейшего пути от корня до любого листа.

Анимация: дерево строится уровень за уровнем слева направо. Жёлтая метка показывает текущий уровень и его глубину; после добавления последнего уровня золотая стрелка проходит по самому длинному пути к листу -- это высота дерева H.

Формулы для полного двоичного дерева

Полное двоичное дерево -- структура, в которой каждый нелистовой узел имеет ровно двух потомков, а все листья находятся на одном уровне. Если дерево состоит из nn уровней (уровни 0,1,,n10, 1, \ldots, n-1):

ХарактеристикаФормула
Высота дерева HHH=n1H = n - 1
Глубина узла уровня kkd=kd = k
Число узлов на уровне kk2k2^k
Суммарное число узлов2n12^n - 1
Число листьев2n1=2H2^{n-1} = 2^H

Эти соотношения легко проверить: на уровне 0 -- один корень (20=12^0 = 1), на уровне 1 -- два узла (21=22^1 = 2), на уровне 2 -- четыре (22=42^2 = 4) и так далее. Суммарно по геометрической прогрессии:

k=0n12k=2n1.\sum_{k=0}^{n-1} 2^k = 2^n - 1.

Отсюда и обратная формула: если в полном двоичном дереве NN узлов, то его высота H=log2NH = \lfloor \log_2 N \rfloor.

Полное двоичное дерево: уровни 0-3, глубина и счётчики узлов на каждом уровне
Полное двоичное дерево: уровни 0-3, глубина и счётчики узлов на каждом уровне

Высота вырожденного дерева

Вырожденное (или патологическое) дерево -- это крайний случай: каждый нелистовой узел имеет ровно одного потомка. Такое дерево структурно эквивалентно связному списку. При nn узлах:

H=n1,листьев=1.H = n - 1, \quad \text{листьев} = 1.

Алгоритм двоичного поиска в таком дереве деградирует до линейного: на каждом уровне одна ветвь, поэтому поиск элемента требует O(n)O(n) шагов вместо O(logn)O(\log n) в сбалансированном дереве. Именно для предотвращения вырождения придуманы AVL-деревья и красно-чёрные деревья -- они гарантируют, что высота не превысит O(logn)O(\log n).

Рассмотрим пример: вставим ключи 1,2,3,4,51, 2, 3, 4, 5 в BST без балансировки в порядке возрастания. Каждый новый ключ окажется правым потомком предыдущего, и дерево вытянется в прямую линию. Глубина узла со значением 5 будет равна 4, высота всего дерева тоже 4 -- хотя в полном двоичном дереве из 5 узлов H=log25=2H = \lfloor \log_2 5 \rfloor = 2. Это наглядно показывает, насколько важна очерёдность вставки для неавтобалансирующихся деревьев.

Рекурсивный алгоритм вычисления высоты

Высоту дерева можно найти рекурсивно: высота пустого дерева равна 1-1 (или 00 в соглашении «считаем узлы»), высота листа -- 00, высота нелистового узла -- максимум высот его поддеревьев плюс единица:

h(v)={1,v=None0,v – лист1+max(h(v.left), h(v.right)),иначеh(v) = \begin{cases} -1, & v = \text{None} \\ 0, & v \text{ -- лист} \\ 1 + \max(h(v.\text{left}),\ h(v.\text{right})), & \text{иначе} \end{cases}

Псевдокод:

def height(node):
    if node is None:
        return -1
    return 1 + max(height(node.left), height(node.right))

Алгоритм обходит каждый узел ровно один раз, поэтому временная сложность -- O(n)O(n), а пространственная -- O(H)O(H) (глубина стека рекурсии).

Глубина узла считается иначе -- не рекурсией вниз, а обходом вверх (или сверху вниз с передачей текущей глубины):

def depth(node, target, d=0):
    if node is None:
        return -1
    if node == target:
        return d
    left = depth(node.left, target, d + 1)
    if left != -1:
        return left
    return depth(node.right, target, d + 1)

Связь между высотой и числом узлов

Для любого двоичного дерева с NN узлами высота удовлетворяет двусторонней оценке:

log2NHN1.\lfloor \log_2 N \rfloor \leq H \leq N - 1.

Левая граница достигается на полном дереве, правая -- на вырожденном. Это неравенство объясняет, почему инженеры так заботятся о балансировке: разница между log2N\log_2 N и N1N - 1 для больших NN огромна. Например, при N=1000000N = 1\,000\,000: Hmin=19H_{\min} = 19 против Hmax=999999H_{\max} = 999\,999.

Параллельное сравнение: слева полное двоичное дерево (H = log N), справа вырожденное (H = N - 1). Золотая стрелка показывает путь поиска в каждом случае -- разница в числе шагов нарастает с ростом N.

Высота в стандартных структурах данных

Высота имеет прямое значение в нескольких структурах:

  • Двоичное дерево поиска (BST). Без балансировки высота зависит от порядка вставки: при случайных ключах ожидаемая H2lnNH \approx 2 \ln N, в худшем случае H=N1H = N - 1 (вставка уже отсортированного ряда).
  • AVL-дерево. Гарантирует H1,44log2(N+2)H \leq 1{,}44 \log_2(N + 2). Балансировка выполняется поворотами при нарушении «баланс-фактора» (h(left)h(right)1|h(\text{left}) - h(\text{right})| \leq 1 в каждом узле).
  • Красно-чёрное дерево. Гарантирует H2log2(N+1)H \leq 2 \log_2(N + 1).
  • Куча (heap). Хранится в массиве, логически образует полное дерево; высота H=log2NH = \lfloor \log_2 N \rfloor.
  • B-дерево. Используется в базах данных и файловых системах; каждый узел хранит от t1t-1 до 2t12t-1 ключей (параметр tt -- минимальная степень). Высота B-дерева не превышает logtN+12\log_t \frac{N+1}{2}, что позволяет существенно сократить число дисковых операций по сравнению с двоичными деревьями.

Зная высоту дерева в конкретной реализации, можно сразу оценить трудоёмкость операций. Например, в AVL-дереве с N=106N = 10^6 узлов H1,442029H \leq 1{,}44 \cdot 20 \approx 29 -- это означает не более 29 сравнений при поиске, независимо от того, в каком порядке вставлялись данные.

Частые ошибки

  • Путаница «высота» и «глубина». Глубина -- свойство узла (расстояние от корня вниз), высота -- тоже свойство узла, но в обратном направлении (от него до листа). Высота дерева = высота корня. Новички нередко подставляют глубину туда, где нужна высота.
  • Несогласованность соглашения о нумерации. В одних источниках высота листа равна 0, в других -- 1. Число уровней nn и высота HH тоже соотносятся по-разному (H=n1H = n-1 или H=nH = n). Перед решением задачи уточни, какое соглашение принято.
  • Неверная рекурсия для пустого поддерева. Если возвращать h(None)=0h(\text{None}) = 0, а не 1-1, листья получат высоту 1 вместо 0. Это сдвигает все значения на единицу.
  • Смешение высоты дерева и максимальной глубины листа. Оба значения совпадают по определению, но при реализации через разные алгоритмы (сверху вниз и снизу вверх) легко получить расхождение из-за ошибки в базовом случае.
  • Игнорирование вырождения при вставке. При вставке уже отсортированного массива в BST без балансировки дерево вырождается в список: высота становится N1N - 1 вместо log2N\log_2 N.

FAQ

Чем отличается высота от глубины в дереве? Глубина узла -- расстояние от корня до этого узла (метрика сверху вниз). Высота узла -- длина самого длинного пути от этого узла до листа (метрика снизу вверх). У одного и того же узла глубина и высота обычно разные числа; совпадают только в вырожденных случаях.

Как посчитать высоту двоичного дерева с n узлами? Зависит от структуры дерева. Для полного двоичного дерева с nn уровнями H=n1H = n - 1. Для произвольного BST из NN узлов -- рекурсивно: h(v)=1+max(h(v.left),h(v.right))h(v) = 1 + \max(h(v.\text{left}), h(v.\text{right})), h(None)=1h(\text{None}) = -1. Нижняя оценка: Hlog2NH \geq \lfloor \log_2 N \rfloor.

Почему высота влияет на скорость операций в дереве? Операции поиска, вставки и удаления в BST занимают O(H)O(H) шагов: на каждом шаге спускаемся на один уровень. При сбалансированном дереве H=O(logN)H = O(\log N) -- быстро. При вырождении H=O(N)H = O(N) -- медленно, как линейный поиск. Поэтому балансировка деревьев так важна для производительности.

Коротко

Глубина узла -- расстояние от корня до узла, высота узла -- длина длиннейшего пути вниз до листа. Высота дерева HH -- это высота корня. Для полного двоичного дерева с nn уровнями: H=n1H = n - 1, на уровне kk ровно 2k2^k узлов, всего 2n12^n - 1. Вырожденное дерево из NN узлов имеет H=N1H = N - 1 -- это нижний предел эффективности, который балансировка (AVL, красно-чёрное дерево) сводит к O(logN)O(\log N).

Доверьте текст нейросети EssayAI

Открыть EssayAI

Бесплатно, на русском языке и без VPN

Читайте также