8

I have an theoretical question about Balanced BST.

I would like to build Perfect Balanced Tree that has 2^k - 1 nodes, from a regular unbalanced BST. The easiest solution I can think of is to use a sorted Array/Linked list and recursively divide the array to sub-arrays, and build Perfect Balanced BST from it.

However, in a case of extremely large Tree sizes, I will need to create an Array/List in the same size so this method will consume a large amount of memory.

Another option is to use AVL rotation functions, inserting element by element and balancing the tree with rotations depending on the Tree Balance Factor - three height of the left and right sub trees.

My questions are, am I right about my assumptions? Is there any other way to create a perfect BST from unbalanced BST?

OlejkaKL
  • 521
  • 1
  • 9
  • 23
  • Some rotation functions make perfect sense in case you have a large tree and want to transform the tree without changing much of the existing structure. - Does the result really have to be perfectly balanced? What is the background of the question? – michas Dec 24 '12 at 12:20
  • Yes, it have to be perfectly balanced. It's a part of an academic project. What do you mean by "some rotation functions"? As far as i know there are four rotation functions that are quite easy to implement. – OlejkaKL Dec 24 '12 at 12:28
  • Different kind of trees use slightly different ways of rotating. For example compare AVL and red-black trees. – michas Dec 24 '12 at 14:59

3 Answers3

2

AVL and similar trees are not perfectly balanced so I'm not sure how they are useful in this context.

You can build a doubly-linked list out of tree nodes, using left and right pointers in lieu of forward and backward pointers. Sort that list, and build the tree recursively from the bottom up, consuming the list from left to right.

Building a tree of size 1 is trivial: just bite the leftmost node off the list.

Now if you can build a tree of size N, you can also build a tree of size 2N+1: build a tree of size N, then bite off a single node, then build another tree of size N. The singe node will be the root of your larger tree, and the two smaller trees will be its left and right subtrees. Since the list is sorted, the tree is automatically a valid search tree.

This is easy to modify for sizes other than 2^k-1 too.

Update: since you are starting from a search tree, you can build a sorted list directly from it in O(N) time and O(log N) space (perhaps even in O(1) space with a little ingenuity), and build the tree bottom-up also in O(N) time and O(log N) (or O(1)) space.

n. m. could be an AI
  • 112,515
  • 14
  • 128
  • 243
1

I did not yet find a very good situation for needing a perfectly balanced search tree. If your case really needs it, I would like to hear about it. Usually it is better and faster to have a almost balanced tree.

If you have a large search tree, throwing away all existing structure is usually no good idea. Using rotation functions is a good way of getting a more balanced tree while preserving most of the existing structure. But normally you use a suitable data structure to make sure you never have a completely unbalanced tree. So called self balancing trees.

There is for example an AVL tree, a red-black-tree or a splay-tree, which use slightly different variants of rotation to keep the tree balanced.

If you really have a totally unbalanced tree you might have a different problem. - In your case rotating it the AVL way is probably the best way to fix it.

michas
  • 25,361
  • 15
  • 76
  • 121
0

If you are memory constrained, then you can use the split and join operations which can be done on an AVL tree in O(log n) time, and I believe constant space.

If you also were able to maintain the order statistics, then you can split on median, make the LHS and RHS perfect and then join.

The pseudo-code (for a recursive version) will be

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);
}

This can be implemented in O(n) time and O(log n) space, I believe.

TexMan
  • 1