Tips
There are many bad and inefficient ways for doing AVL balancing. Your code should be able to run even the largest tests in the TestDriver in under 10 seconds. If your code is running slow, here are some things to check.
- Is your tree really balanced?
Once you get 90,000 items in a tree, it's hard to check sometimes if the tree is really AVL balanced. An unbalanced tree will start to exhibit O(N)
behavior in it's contains
and insert
methods. Usually, the culprit is in the remove
method.
- Are you re-calculating information that might not be changing?
Store the heights of nodes inside the node object and only update them when they might have changed. Only a small fraction of the nodes in a tree will need to have their heights checked during each insertion and deletion and this fraction gets smaller and smaller as the tree gets bigger and bigger
- Are you using too much recursion?
If you check the heights and the balancing of your tree by calling some recursive method on the root of your tree every time you insert or remove, you are doing too much work. Any time that you insert or remove, the only possible nodes that could need to have their height updated or that might become unbalanced are those along the path from the root node to the inserted note. The insert
and remove
methods should be recursive, and if they are, this path is "stored" in the recursive calls to insert
and remove
. Do your height checking, balance checking, and balancing all as you come out of these recursive calls (after the recursive call in your recursive methods, put the code to do the work for these operations)
Lastly, one thing that you should consider as you design your AVL tree, is what to do when the left and right subtrees are the same height when it comes time to balance. You will recall that the decision as to whether a single or double rotation is needed is made by testing to see if the unbalance is left-left or right-right (both of which result in a single rotation) or left-right or right-left (both of which result in a double rotation). These cases are the only possibilities for insertion. When it comes time to delete, there is a 5th case that is possible. This is the case where node X is the unbalanced node (it's left child and right child have heights that are off by two) and the child with the larger height has two children that now, because of a delete operation, have equal heights.
In this case, your code should "default" to a single rotation! This means that, when you test to see which side is larger, you should make judicious use of the
<=
and the
>=
operators.