Объединение/слияние / объединение двух деревьев AVL
предположим, что у меня есть два дерева AVL и что каждый элемент из первого дерева меньше любого элемента из второго дерева. Каков наиболее эффективный способ объединить их в одно дерево AVL? Я искал везде но не нашел ничего полезного.
4 ответов
предполагая, что вы можете уничтожить входные деревья:
- удалите самый правый элемент для левого дерева и используйте его для создания нового корневого узла, левый дочерний элемент которого является левым деревом, а правый дочерний элемент-правым деревом: O (log n)
- определите и установите коэффициент баланса этого узла: O (log n). При (временном) нарушении инварианта коэффициент баланса может находиться вне диапазона {-1, 0, 1}
- поверните, чтобы вернуть коэффициент баланса в диапазон: O (log N) вращения: O (log n)
таким образом, вся операция может быть выполнена в O(log n).
Edit: с другой стороны, легче рассуждать о вращениях в следующем алгоритме. Это также, скорее всего, быстрее:
- определите высоту обоих деревьев: O (log n).
Предполагая, что правое дерево выше (другой случай симметричен): - удалить правый элемент
left
дерево (вращение и регулировка его вычисленная высота при необходимости). Пустьn
быть этот элемент. O (log n) - в правом дереве перейдите влево, пока не достигнете узла, поддерево которого не более 1 выше
left
. Пустьr
быть этот узел. O (log n) замените этот узел новым узлом со значением n и поддеревьями
left
иr
. O (1)
По конструкции новый узел AVL-сбалансирован, а его поддерево 1 вышеr
.приращение его баланс родителей соответственно. O (1)
- и перебалансировки, как вы бы после вставки. O (log n)
одно ультра простое решение (которое работает без каких-либо предположений в отношениях между деревьями) заключается в следующем:
- выполните слияние обоих деревьев в один объединенный массив (одновременно повторите оба дерева).
- создайте дерево AVL из массива-возьмите средний элемент как корень и примените рекурсивно к левой и правой половинам.
оба шага O (n). Основная проблема заключается в том, что он занимает o(n) дополнительное пространство.
лучшее решение, которое я прочитал для этой проблемы, можно найти здесь. Очень близко к Меритонответ, если вы исправите этот вопрос:
на третьем шаге алгоритма перемещается влево, пока вы не достигнете узла, под дерево которого имеет ту же высоту, что и левое дерево. Это не всегда возможно (см. контрпример image). Правильный способ сделать этот шаг-найти два поддерева с высотой h
или h+1
здесь h
- Это высота левого дерева
Я подозреваю, что вам просто придется ходить по одному дереву (надеюсь, меньшему) и индивидуально добавлять каждый из его элементов к другому дереву. Операции вставки/удаления AVL не предназначены для обработки добавления целого поддерева за раз.