Лекция
Сразу хочу сказать, что здесь никакой воды про декартово дерево по неявному ключу, и только нужная информация. Для того чтобы лучше понимать что такое декартово дерево по неявному ключу , настоятельно рекомендую прочитать все из категории Структуры данных.
Возьмем структуру данных динамический массив. В ее стандартной реализации мы умеем добавлять элемент в конец вектора, узнавать значение элемента, стоящего на определенной позиции, изменять элемент по номеру и удалять последний элемент. Предположим, что нам необходима структура данных с вышеуказанными свойствами, а также с операциями: добавить элемент в любое место (с соответствующим изменением нумерации элементов) и удалить любой элемент (также с соответствующим изменением нумерации). Такую структуру можно реализовать на базе декартового дерева, результат часто называют декартово дерево по неявному ключу (англ. Treap with implicit key).
Как известно, декартово дерево — это структура данных, объединяющая в себе бинарное дерево поиска и бинарную кучу. При реализации же декартова дерева по неявному ключу модифицируем эту структуру. А именно, оставим в нем только приоритет Y , а вместо ключа X будем использовать следующую величину: количество элементов в нашей структуре, находящихся левее нашего элемента. Иначе говоря, будем считать ключом порядковый номер нашего элемента в дереве, уменьшенный на единицу.
Заметим, что при этом сохранится структура двоичного дерева поиска по этому ключу (то есть модифицированное декартово дерево так и останется декартовым деревом). Однако, с этим подходом появляется проблема: операции добавления и удаления элемента могут поменять нумерацию, и при наивной реализации на изменение всех ключей потребуется O(n) времени, где nn — количество элементов в дереве.
Решается эта проблема довольно просто. Основная идея заключается в том, что такой ключ X сам по себе нигде не хранится. Об этом говорит сайт https://intellect.icu . Вместо него будем хранить вспомогательную величину C : количество вершин в поддереве нашей вершины (в поддерево включается и сама вершина). Обратим внимание, что все операции с обычным декартовым деревом делались сверху. Также заметим, что если по пути от корня до некой вершины просуммировать все такие величины в левых поддеревьях, в которые мы не пошли, увеличенные на единицу, то придя в саму вершину и добавив к этой величине количество элементов в ее левом поддереве, мы получим как раз ее ключ X.
Структура обычного декартова дерева поддерживается с помощью двух операций: split — разбиение одного декартова дерева на два таких, что в одном ключ X меньше, чем заданное значение, а в другом — больше, и merge — слияние двух деревьев, в одном из которых все ключи X меньше, чем во втором. С учетом отличий декартова дерева по неявному ключу от обычного, операции теперь будут описываться так: split(root,t) — разбиение дерева на два так, что в левом окажется ровно t вершин, и merge(root1,root) — слияние двух любых деревьев, соответственно.
Пусть процедура split запущена в корне дерева с требованием отрезать от дерева k вершин. Также известно, что в левом поддереве вершины находится l вершин, а в правом r . Рассмотрим все возможные случаи:
Псевдокод:
〈〈Treap, Treap 〉 split(Treap t, int k) if t == ∅ return 〈 ∅, ∅ 〉 int l = t.left.size if l ⩾ k 〈t1, t2〉 = split(t.left, k) t.left = t2 update(t) return 〈t1, t 〉 else 〈t1, t2〉 = split(t.right, k - l - 1) t.right = t1 update(t) return 〈t, t2〉
Посмотрим любую из реализаций процедуры merge. Заметим, что в ней программа ни разу не обращается к ключу X . Поэтому реализация процедуры merge для декартова дерева по неявному ключу вообще не будет отличаться от реализации той же процедуры в обычном декартовом дереве.
Единственное действие, обеспечивающее корректность этих значений заключается в том, что после любого действия с детьми вершины нужно записать в ее поле C сумму этих значений в ее новых детях, увеличенную на единицу.
Псевдокод:
void update(Treap t) t.size = 1 + t.left.size + t.right.size
Таким образом, описана структура, от которой можно отрезать слева часть произвольной длины и слить две любые части в одну в нужном порядке. Теперь мы имеем возможность:
А как ты думаешь, при улучшении декартово дерево по неявному ключу, будет лучше нам? Надеюсь, что теперь ты понял что такое декартово дерево по неявному ключу и для чего все это нужно, а если не понял, или есть замечания, то не стесняйся, пиши или спрашивай в комментариях, с удовольствием отвечу. Для того чтобы глубже понять настоятельно рекомендую изучить всю информацию из категории Структуры данных
Из статьи мы узнали кратко, но содержательно про декартово дерево по неявному ключу
Комментарии
Оставить комментарий
Структуры данных
Термины: Структуры данных