1. 1

# конспект · шаг 1 из 1

Конспект раздела: деревья поиска

выжимка - её можно унести в заметки

Карта раздела

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

BST                  ->  инвариант «левое < узел < правое»; всё за O(h); отсортированный ввод → цепочка h=n
     |
балансировка         ->  вращение O(1) хранит порядок; АВЛ (разница высот ≤1), красно-чёрное (цвет)
     |
B-деревья            ->  узел = дисковый блок на сотни ключей; высота log_b n: при b = 500 и 10⁹ ключей - 3-4 чтения
     |
случайность          ->  декартово (приоритеты), splay (амортизация), skip list (случайные уровни)
     |
дополнение           ->  поле в узле, восстановимое из детей: size → ранг, max → пересечение
     |
диапазоны            ->  дерево отрезков, Фенвик, lazy: запрос и обновление диапазона за log n

Сводная таблица деревьев

структура высота / цена гарантия когда
голый BST O(h), до n нет только учебно
АВЛ ≤ 1.44·log₂ n + 1 худший случай поиск ≫ правки
красно-чёрное ≤ 2·log₂(n+1) худший случай универсал (std::map, TreeMap)
B / B+-дерево log_b n, 3-4 чтения худший случай диск: индексы БД, ФС
декартово (treap) O(log n) ожидание простота, SPLIT/MERGE
splay O(log n) амортизация горячие данные
список с пропусками O(log n) ожидание простота, параллелизм
дерево отрезков O(log n) запрос/обновление худший случай диапазоны, любая свёртка
дерево Фенвика O(log n) худший случай динамические суммы

Три компромисса раздела

Строгость баланса против частоты правок. АВЛ ниже, но чаще вращает; красно-чёрное выше, но чинится реже (часто перекраской). Идеала «низко И редко чинить» нет.

Гарантия против ожидания. АВЛ/красно-чёрное дают O(log n) в худшем случае; treap и skip list - в ожидании (случайность внутри, вход подобрать нельзя); splay - амортизированно.

Цена зависит от уровня памяти. В памяти оптимум - двоичное дерево (считаем сравнения); на диске - широкий узел B-дерева (считаем чтения блоков): ветвление уходит в основание логарифма.

Два приёма, которые переносятся дальше

Вращение - атом балансировки: O(1), хранит порядок (серединное поддерево перевешивается на нужное место). Из него собраны АВЛ, красно-чёрное, декартово, splay.

Дополнение - добавь в узел поле, восстановимое из детей за O(1), - и получишь новую операцию, не ломая старых и не мешая вращениям. Дерево отрезков - этот же приём, доведённый до диапазонов; отложенные метки добавляют к нему ленивость.

Ловушки джокера всего раздела

Голый BST на отсортированных или потоковых данных - вырождение в цепочку, Θ(n).

Потерять серединное поддерево при вращении - дерево перестаёт быть BST.

Одинарный поворот для ломаного случая LR/RL - нужен двойной.

Двоичное дерево для дискового индекса - ~30 чтений вместо 3-4.

Считать treap, skip list или splay гарантией на каждую операцию - это ожидание или амортизация.

Поле дополнения, не восстановимое из детей - вращения станут O(n).

Префиксные суммы при обновлениях, Фенвик для min/max, забытый push_down в запросе.

Последовательность, которая меняет порядок

Задача Инструмент Условие или граница
Вставка, вырезание, разворот Неявное декартово дерево split по размеру и merge по порядку; ожидаемый логарифм при случайных приоритетах.
Сумма меняющегося диапазона total в поддереве Два split, ответ из корня, два merge; разворот сохраняет total.

Проверь себя

Почему цена операций дерева - высота и что её портит?

Как вращение меняет форму, не трогая порядок, и чем АВЛ отличается от красно-чёрного?

Почему индексы БД - B-деревья, а std::map - красно-чёрное?

Как случайность (treap, skip list) и амортизация (splay) заменяют явную балансировку?

Как поле в узле даёт новую операцию и чем дерево отрезков отличается от Фенвика?

Комментарии

Пока нет комментариев. Будь первым!

Оставить комментарий

Комментарий появится после проверки. Email не публикуется. Войти, чтобы не вводить имя каждый раз.