1. 1
  2. 2
  3. 3
  4. 4
  5. 5

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

Конспект: дополненные деревья

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

Понятия

Дополнение дерева - приём: добавить в узел ПОЛЕ, восстановимое из полей детей за O(1), и получить новую операцию, НЕ ломая старые (поиск, вставку, удаление, баланс). Поле обновляют на пути вставки/удаления и при ВРАЩЕНИЯХ (O(1) на узел).

Поле size (число узлов поддерева = 1 + size(лево) + size(право)) даёт: - SELECT(k) - k-й по порядку элемент: в узле L = size(лево), ранг узла L+1; k==L+1 - ответ, k<=L - влево, иначе вправо с k = k − L − 1. O(log n). - RANK(x) - место ключа: сумма размеров левых поддеревьев там, где уходим вправо. O(log n).

Поле max (наибольший правый конец отрезков поддерева) в BST по левому концу даёт поиск ПЕРЕСЕКАЮЩЕГО отрезка: если max(лево) < l, все левые кончаются раньше l - отбрасываем поддерево, идём вправо. O(log n).

Локальность поля - ключевое условие: пересчёт из детей за O(1) позволяет обновлять поле при вращениях, не обходя поддерево, - потому балансировка сохраняется.

Что унести

Дополнение - это ОДИН шаблон, а не набор трюков:

1. взять сбалансированное BST
2. добавить в узел поле, восстановимое из детей за O(1)
3. обновлять поле при вставке/удалении и при вращениях (O(1) на узел)
4. новая операция СПУСКАЕТСЯ по дереву, используя поле, чтобы отбросить поддерево

Меняется только ПОЛЕ и правило спуска:

поле операция
size (число узлов) select (k-й), rank (место)
max правого конца пересечение отрезков
сумма поддерева диапазонные суммы
min / max ключа быстрые экстремумы поддерева

Дополнение даёт то, чего не может ни хеш (нет порядка), ни массив (дорогая вставка), ни обычное дерево (нет рангов/диапазонов): ДИНАМИЧЕСКИЕ порядковые и диапазонные запросы за O(log n). Главная мысль - не конкретная структура, а МЕТОД: встретив «нестандартный» запрос, спроси «каким локальным полем дополнить дерево, чтобы ответить спуском?». Дерево отрезков и Фенвика (следующая глава) - это тот же приём, доведённый до диапазонных запросов.

Ловушки джокера

Поле, не восстановимое из детей локально (глубина, глобальный индекс) - вращение потребует обхода поддерева, O(1)-баланс сломается. Дополняют полем, зависящим только от детей.

Не обновлять поле при вращениях (только при вставке/удалении) - после балансировки поле неверно, операция врёт.

Для порядковой статистики взять высоту вместо размера - высота не говорит, сколько элементов слева.

В select ошибиться с поправкой при уходе вправо - вычитать size(лево) + 1 (левое поддерево И сам узел), не только size(лево).

Для пересечения взять не max правого конца - только он позволяет отбросить «все кончаются раньше l».

Ждать все пересечения за O(log n) - за O(log n) находится одно; все k - дороже.

Проверь себя

В чём приём дополнения и почему поле должно восстанавливаться из детей за O(1)?

Как поле size даёт select и rank за O(log n)?

Каким полем и как интервальное дерево находит пересекающийся отрезок?

Почему интервальное дерево и дерево порядковой статистики - один шаблон?

Какое поле дало бы диапазонные суммы?

Комментарии

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

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

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