Идеальное Сбалансированное Бинарное Дерево Поиска

у меня есть теоретический вопрос о Balanced BST.

Я хотел бы построить Perfect Balanced Tree и 2^k - 1 узлы, от обычного unbalanced BST. Самое простое решение, которое я могу придумать, - использовать сортированный Array/Linked list и рекурсивно разделить массив на подмассивы, и построить Perfect Balanced BST от него.

однако, в случае чрезвычайно больших размеров дерева, мне нужно будет создать Array/List в таком же размере поэтому этот метод уничтожит большое количество память.

другой вариант-использовать AVL функции вращения, вставка элемента за элементом и балансировка дерева с вращениями в зависимости от коэффициента баланса дерева - три высоты левого и правого под деревьев.

мои вопросы, я прав насчет моих предположений? Есть ли другой способ создать идеальный BST от несбалансированного BST?

3 ответов


Я еще не нашел очень хорошую ситуацию для необходимости идеально сбалансированного дерева поиска. Если ваше дело действительно нуждается в этом, я хотел бы услышать об этом. Обычно лучше и быстрее иметь почти сбалансированное дерево.

Если у вас есть большое дерево поиска, выбрасывание всей существующей структуры обычно не является хорошей идеей. Использование функций вращения-хороший способ получить более сбалансированное дерево при сохранении большей части существующей структуры. Но обычно вы используете подходящие данные структура, чтобы убедиться, что у вас никогда не будет полностью неуравновешенного дерева. Так называемые самобалансирующиеся деревья.

существует, например, дерево AVL, красно-черное дерево или splay-дерево, которые используют несколько разные варианты вращения, чтобы сохранить равновесие дерева.

Если у вас действительно есть совершенно несбалансированное дерево у вас может быть другая проблема. - В вашем случае вращение его AVL-это, вероятно, лучший способ его исправить.


AVL и подобные деревья не отлично сбалансированный, поэтому я не уверен, насколько они полезны в этом контексте.

вы можете построить дважды связанный список из узлов дерева, используя left и right указатели вместо forward и backward указатели. Отсортируйте этот список и постройте дерево рекурсивно снизу вверх, потребляя список слева направо.

построение дерева размера 1 тривиально: просто откусите самый левый узел от список.


Если вы ограничены памятью, то вы можете использовать операции разделения и соединения, которые могут быть выполнены на дереве AVL в O(log n) времени, и я считаю, что постоянное пространство.

Если вы также смогли поддерживать статистику заказа, то вы можете разделить на медиану, сделать LHS и RHS совершенными, а затем присоединиться.

псевдо-код (для рекурсивной версии) будет

void MakePerfect (AVLTree tree) {

    Tree left, right;
    Data median;

    SplitOnMedian(tree, &left, &median, &right);
    left = MakePerfect(left);
    right = MakePerfect(right);
    return Join(left, median, right);
}

Это может быть реализовано в O(n) времени и o (log n) пространстве, я считаю.