Обновление: см. Ниже обновление о неправильности этой операции соединения
Вот очень грубый набросок возможного решения:
Я думаю, что у меня может быть решение этой проблемы с использованием типа случайно сбалансированного B + -дерева. Как и у ловушек, эти деревья имеют уникальное представление. В отличие от трэпов, они хранят несколько ключей несколько раз. Возможно, это можно исправить, используя трюк из «Biased Search Trees» Бента и др., В котором каждый ключ хранится только на самом высоком (то есть ближайшем к корню) уровне, на котором он появляется).
Дерево для упорядоченного набора уникальных значений создается путем первого связывания каждого значения с потоком битов, аналогично тому, как каждое значение в трэпе связано с приоритетом. Каждый узел в дереве содержит как ключ, так и поток битов. Нелистовые узлы содержат, кроме того, натуральное число, указывающее высоту дерева, укорененного в этом узле. Внутренние узлы могут иметь любое ненулевое количество дочерних узлов. Как и в случае B + -деревьев, каждый несамопересекающийся путь от корня до листа имеет одинаковую длину.
Каждый внутренний узел содержит (как в B + -деревьях) самый большой ключ k своего потомка. Каждый из них также содержит натуральное число i, указывающее высоту дерева с корнем в v , и поток битов, связанных с k, начиная с i + 1- го бита и далее. Если каждый ключ в дереве с корнем v имеет один и тот же первый бит в своем потоке битов, каждый дочерний элемент v является листом, а i равно 1 . В противном случае дочерние элементы v являются внутренними узлами, каждый из которых имеет одинаковый i- й бит в потоке битов, связанном с их ключом.vkivki+1vvi1vi
Чтобы создать дерево из отсортированного списка ключей со связанными битовыми потоками, сначала соберите ключи в смежные группы на основе первого бита в их потоках. Для каждой из этих групп создайте родителя с ключом и потоком битов самого большого ключа в группе, но исключая первый бит потока. Теперь сделайте ту же процедуру группировки новых родителей, чтобы создать бабушку и дедушку. Продолжайте, пока не останется только один узел; это корень дерева.
Следующий список ключей и (начало) битовых потоков представлен деревом под ним. В префиксах битового потока - «.» значит любой бит. То есть любой поток битов для ключа A с нулем в первую очередь создает то же дерево, что и любой другой, при условии, что поток битов другого ключа не отличается.
A 0...
B 00..
C 10..
D 0...
E 0011
F 1...
G 110.
H 0001
____H____
/ \
E H
| / \
__E__ G H
/ | \ | |
B C E G H
/ \ | / \ / \ |
A B C D E F G H
Каждый дочерний элемент определенного внутреннего узла имеет одинаковый бит в первую очередь своего потока битов. Это называется «цвет» родителя - 0 красный, 1 зеленый. У ребенка есть «аромат» в зависимости от первого бита его потока битов - 0 - вишня, 1 - мята. Листья имеют вкус, но не имеют цвета. По определению узел вишни не может иметь зеленого родителя, а узел мяты не может иметь красного родителя.
n21−n (n−1i−1)(n+1)/2n≥2≤34nO(lgn)
Чтобы соединить два дерева одинаковой высоты, сначала проверьте, имеют ли их корни один и тот же цвет. Если это так, отделите от левого корня его самый правый дочерний элемент, а от правого корня - его самый левый дочерний элемент, а затем рекурсивно соедините эти два дерева. Результатом будет дерево той же высоты или одного более высокого роста, поскольку деревья имеют одинаковый вкус (см. Ниже). Если результат рекурсивного соединения двух деревьев имеет ту же высоту, что и два отрубленных потомка, сделайте его средним потомком корня с оставшимися потомками левого корня до него и оставшимися потомками правого корня после него. Если оно на 1 больше, сделайте его потомками средних потомков корня, оставшихся потомков левого корня до него и оставшихся потомков правого корня после него. Если корни имеют разные цвета, проверьте, имеют ли они одинаковый вкус. Если они это сделают, дать им нового родителя с ключом и битовым потоком правого корня, исключая его первый бит. Если они этого не делают, присвойте каждому корню нового родителя с ключом и потоком битов старого корня (исключая каждый первый бит), а затем рекурсивно соедините эти деревья.
1/21/2O(1)1/4и последующие рекурсивные вызовы всегда выполняются на деревьях разных цветов, поэтому применяется один и тот же анализ.
1/2O(1)
O(1)
a 01110
b 110..
c 10...
d 00000
Дерево, созданное им, [a,b]
имеет высоту 2, дерево, созданное им, [c,d]
имеет высоту 2, а дерево, созданное им, joinEqual (tree [a,b]) (tree [c,d])
имеет высоту 3. Однако дерево, созданное им, [a,b,c,d]
имеет высоту 5.
Вот код, который я использовал, чтобы найти эту ошибку .