



Study with the several resources on Docsity
Earn points by helping other students or get them with a premium plan
Prepare for your exams
Study with the several resources on Docsity
Earn points to download
Earn points by helping other students or get them with a premium plan
Material Type: Notes; Class: DATA STRUCTURES; Subject: Computer Science; University: Oregon State University; Term: Summer 2006;
Typology: Study notes
1 / 7
This page cannot be seen from the preview
Don't miss anything!




The time required to perform operations on a binary search tree is proportional to the length of the path from root to leaf. This isn’t bad in a well-balanced tree. But nothing prevents a tree from becoming unbalanced. In the extreme, such as the tree shown on the right, the tree reduces to nothing more than a linked list, and the path from root to leaf is O(n). To preserve fast performance we need to ensure that the tree remains well balanced. One way to do this is to notice that the search tree property has some flexibility. Three nodes that are unbalanced can be restored by a rotation, making the right child into the new root, with the previous root as the new left child. Any existing left child of the old right child becomes the new right child of the new left child. The resulting tree is still a binary search tree, and has better balance. This is known as a left rotation. There is also a corresponding right rotation. There is one case where a simple rotation is not sufficient. Consider an unbalanced tree with a right child that itself has a left child. If we perform a rotation, the result is still unbalanced. The solution is to first perform a rotation on the child, and then rotate the parent. This is termed a double rotation.
The data structure termed the AVL tree was designed using these ideas. The name honors the inventors of the data structure, the Russian mathematicians Georgii M. Adel'son-Vel'ski\u{\i} and Evgeni\u{\i} Mikha\u{\i}lovich Landis. In order to know when to perform a rotation, it is necessary to know the height of a node. We could calculate this amount, but that would slow the algorithm. Instead, we modify the Node so that each node keeps a record of its own height. A method h(Node) will be useful to determine the height of a child node. Since leaf nodes have height zero, a value of - 1 is returned for a null value. Using this, a method setHeight can be defined that will set the height value of a node, assuming that the height of the child nodes is known: int h(struct AVLNode * current) {if (current == null) return - 1; return current.height;} void setHeight (struct AVLNode * current) { int lch = h(current.leftChild); int rch = h(current.rightChild); if (lch < rch) current.height = 1 + rch; else current.height = 1 + lch; } Armed with the height information, the AVL tree algorithms are now easy to describe. The addition and removal algorithms for the balanced binary search tree are modified so that their very last step is to invoke a method balance : struct AVLNode * AVLaddNode (struct AVLNode * current, EleType newValue) { if (current == null) return new Node(newValue, null, null); if (LT(newValue, current.value)) current.leftChild = AVLaddNode (current.leftChild, newValue); else current.rightChild = AVLaddNode (current.rightChild, newValue); return balance(current); // NEW – call balance on result } The function balance performs the rotations necessary to restore the balance in the tree. Let the balance factor be the difference in height between the right and left child trees. This is easily computed using a function. If the balance factor is more than 2, that is, if one subtree is more than two levels different in height from the other, then a rebalancing is performed. A check must be performed for struct AVLNode { EleType value; struct AVLNode *left; struct AVLNode *right; int height; };
Complete the implementation of the AVLtree abstraction by writing the methods to perform a left and right rotation. Both these methods should call setHeight on both the new interior node that has been changed and the new root. Other methods that are similar to those of the Binary Search Tree have been omitted: void AVLTreeInit (struct AVLtree *** tree) { }** void AVLtreeAdd (struct AVLtree *tree, EleType d) { … } void AVLtreeContains (struct AVLtree *tree, EleType d) { } void AVLtreeRemove (struct AVLtree *tree, EleType d) { } int h (struct AVLnode * current) {if (current == null) return - 1; return current.height;} int bf (struct AVLnode * current) { return h(current.rightChild) - h(current.leftChild); } struct AVLnode * balance (struct AVLnode * current) { … } void setHeight (struct AVLnode * current) { … } struct AVLnode * rotateLeft (struct AVLnode * current) {
struct AVLnode * rotateRight (struct AVLnode * current) { }
These equations are very similar to the famous Fibonacci numbers defined by the formula f 0 = 0, f 1 = 1, fn+1 = fn- 1 + fn. An induction argument can be used to show that Mh = fh+3 – 1. It is easy to show using induction that we can bound the Fibonacci numbers by 2n. In fact, it is possible to establish an even tighter bounding value. Although the details need not concern us here, the Fibonacci numbers have a closed form solution; that is, a solution defined without using recursion. The value Fh is approximately $\frac{\Phi^i}{\sqrt{5}}$, where $\Phi$ is the golden mean value $(1+\sqrt{5})/2$, or approximately $1.618$. Using this information, we can show that the function Mh also has an approximate closed form solution: By taking the logarithm of both sides and discarding all but the most significant terms we obtain the result that h is approximately 1.44 log Mh. This tells us that the longest path in a height-balanced binary tree with n nodes is at worst only 44 percent larger than the log n minimum length. Hence algorithms on height- balanced binary trees that run in time proportional to the length of the path are still O(log n). More importantly, preserving the height balanced property is considerably easier than maintaining a completely balanced tree. Because AVL trees are fast on all three bag operations they are a good general purpose data structure useful in many different types of applications.