Оновлення: див. Нижче для оновлення про некоректність цієї операції приєднання
Ось дуже приблизний ескіз можливого рішення:
Я думаю, що я можу вирішити цю проблему, використовуючи тип випадково врівноваженого B +-дерева. Як і трави, ці дерева мають унікальне уявлення. На відміну від трепів, вони зберігають деякі ключі кілька разів. Можна виправити, що за допомогою хитрості "Biased Trees" від Bent et al зберігати кожну клавішу можна лише на найвищому (тобто найближчому до кореня) рівні, на якому вона відображається)
Дерево для впорядкованого набору унікальних значень створюється шляхом спочатку асоціювання кожного значення з потоком бітів, аналогічно тому, як кожне значення в трейпі асоціюється з пріоритетом. Кожен вузол у дереві містить і ключ, і бітовий потік. Крім листяних вузлів, крім того, є натуральне число, що вказує на висоту дерева, вкоріненого у цьому вузлі. Внутрішні вузли можуть мати будь-яку ненульову кількість дітей. Як і B + -трець, кожен непересічний шлях від кореня до листка має однакову довжину.
vkivki+1vvi1vi
Щоб створити дерево з відсортованого списку ключів з пов’язаними потоками бітів, спочатку збирайте ключі в суміжні групи на основі першого біта в їх потоках. Для кожної з цих груп створіть батьківську програму з ключовим і бітовим потоком найбільшого ключа в групі, але викреслюючи перший біт потоку. Тепер виконайте ту саму процедуру групування для нових батьків, щоб створити бабусь і дідусів. Продовжуйте, поки не залишиться лише один вузол; це корінь дерева.
Наступний список клавіш і (початок) потоків бітів представлений деревом під ним. У префіксах бітових потоків, '.' означає будь-який шматочок. Тобто, будь-який потік бітів для ключа A з 0, в першу чергу, створює те саме дерево, що і будь-яке інше, припускаючи, що жоден бітовий потік іншого ключа не відрізняється.
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.
Ось код, який я використав, щоб знайти цю помилку .