Сбалансированные деревья, часть 1
- Не сбалансированное дерево (1960, Windley + Booth + Colin + Hibbard)
- Определение дерева поиска. Сколько деревьев соответствует одной перестановке?
- Хранение: бинарное, произвольное, упорядочить вершины и хранить только отца, хранение дерева в файле
- insert (две версии: обычная и персистентная)
- find, right/left neighbour, erase
- Обходы дерева: симметричный (сортированный массив), прямой (хранение и восстановление дерева)
- Вывод дерева: дерево → массив; дерево → 2D-картинка
- Определения: глубина вершины, средняя глубина вершины, глубина дерева, случайное дерево (добавляем случайную перестановку)
- Lm: сумма размеров поддеревьев равна сумме глубин
- Оценка средней глубины случайного дерева 2ln(n) (ссылаемся на QuickSort)
- Оценка максимальной глубины дерева, полученного при добавлении случайной перестановки 4ln(n) (только формулировка)
- Все операции работают за O(h). Теперь пытаемся ограничить высоту.
- Сортировка деревом, LowerBound на вставку O(logn).
- Вспоминаем сортированный массив и хеш-таблицу. Insert и LowerBound O(h), Del за O(1), Find за O(1)
- Что потом делать с Find, если он вернул указатель на вершину? Ссылки на предков.
- Операции next и prev, прошивка дерева (next и prev за O(1) в худшем, дерево + двусвязный список)
- AVL (1962, Adelson-Velsky + Landis)
- Определение, инвариант высот
- Оценки на size[h], h[size]
- Хранение, удобства реализации:
node::null
; calc()
: size, h
- small/big rotation, insert, выражение big rotation через 2 small rotation
- Оценка количества вращений при insert: O(1)
- Удаление. Максимальное количество вращений равно h/2.
- [не успеем] Операция на отрезке L ≤ x ≤ R: сумма x, сумма y, минимум по y.
- [не успеем] Операция на отрезке L ≤ x ≤ R: увеличить все y на dy, присвоить всем y некоторое значение y0 (модификация на отрезке, проталкивание информации вниз)
- Напоминание: операция find за O(1).
- Идея неявного ключа (implicit key)
- Поддержка размеров поддеревьев, ответ на запрос k-й элемент
- Неявный ключ, массив с операциями insert(i, x), erase(i) за O(logn)
- Персистентное дерево (persistent tree)
- Определение персистентной структуры данных: любая операция изменения, например insert, не меняет старую и возвращает новую структуру данных
- Примитивная структура: персистентный массив с O(1) на обращение и O(n) на модификацию
- Примитивная структура: персистентный массив с O(n) на обращение и O(1) на модификацию
- Персистентное дерево поиска. Массив корней и ацикличный граф. Копирование пути от корня до вершины. Картинка для добавления нового элемента.
- Персистентное AVL дерево: все функции вместо того, чтобы менять старые вершина, создают новые. Пример с вращениями.
- Оценка времени: не поменялось. Оценка памяти: O(nlogn) после n операций.
- Декартово Дерево (treap, дерамида, дуча, курево) (1989 Aragon + Seidel)
- Определение, примеры. Наивный алгоритм построения.
- Единственность декартового дерева (поддерево декартово дерева является декартовым деревом, далее индукция)
- Оценка средней глубины, оценка макисмальной глубины, доказательство того, что наивный алгоритм построения работает за O(nlogn).
- Операции split и merge
- Операции insert и erase через split, merge
- Операция insert через 1 split (а вот delete через 1 merge на практике)
- Замечание про равные ключи
- {x, count} (для каждого x есть ровно одна вершина)
- {x, какой-то ключ различающий x-ы} (для каждого x есть столько вершин, сколько раз x входит, но все пары различны)
- Всё делать через split и merge, которые не меняют порядок
- [не успеем] Декартово дерево по неявному ключу: rotate(a, a+k, a+n) за O(logn)
- [не успеем] В декартовом дереве по неявному ключу можно хранить массив (доступ к элементу за O(logn) + дополнительные операции)
- Peristent world
- Peristent tree уже было
- Peristent array: tree + implicit key