Идеальное Сбалансированное Бинарное Дерево Поиска
у меня есть теоретический вопрос о 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) пространстве, я считаю.