2010 October 16 / |j|d|a|v|i|s|@|c|a|r|l|e|t|o|n|.|e|d|u

Assignment: AVL Trees

Carleton College CS 201, Prof. Joshua R. Davis

Introduction

The purpose of this short assignment is to understand the AVL tree. Recall that an AVL tree is approximately balanced, in that at each node the height of the left and right subtrees differ by at most one. Maintaining this level of balance keeps the height of the tree small relative to the number of nodes, and hence keeps all of our binary search tree operations fast.

Because height is used so frequently in an AVL tree, it makes sense for each node to store its height (meaning the height of the tree hanging off it), rather than recompute the height each time it's needed. Thus an AVL tree node stores a key, a value, and a height, whereas an ordinary binary search tree node stores just a key and a value. We could make our AVLTreeNode class a subclass of BinarySearchTreeNode, but the methods (specifically put and delete) are sufficiently different that we'll implement AVLTreeNode as a new subclass of BinaryTreeNode.

In fact, I've already written most of the implementation for you, by modifying BinarySearchTreeNode's code to perform balancing operations recursively after each put and delete operation. You are required to write the AVL balancing operation; then AVLTreeNode is finished. Then you are required to implement IntDictionary and Dictionary atop AVLTreeNode.

You may complete this assignment with one partner, although it's not the kind of work that's easily divided up. It is due Wednesday at 11:59 PM.

Complete AVLTreeNode

Download the file avltreenode.py to your computer. Most of it has been written for you already. There are various methods for getting and setting height. The get method is identical to BinarySearchTreeNode's. The put and delete methods have been modified (from BinarySearchTreeNode's versions) to rebalance the tree, by calling the balance method. So they're done. But right now balance does very little; it just updates the height, without actually balancing anything. Your job is to implement balance for real.

Remember from class that we use two fundamental "rotation" operations to balance a tree. In the illustration below, individual nodes are drawn as circles, and subtrees are drawn as triangles. In the tree on the left, a left rotation at node 1 produces the tree on the right. That is, the left rotation shifts node 2 up to the root, shifts node 1 into node 2's left subtree, and reconfigures all other parts of the tree in the only way possible, that maintains the binary search tree property. The right rotation is simply the inverse operation; that is, in the tree on the right, a right rotation at node 2 produces the tree on the left.

Now, a put or delete operation on an AVL tree node may temporarily put a tree node out of AVL balance. There are four possible ways in which a node can be out of balance, called RR, LL, RL, and LL. The RR case is illustrated on the left side of the figure below. It occurs when the height of the right subtree of node 1 exceeds the height of the left subtree of node 1 by more than one, and the right subtree of node 2 is at least as tall as the left subtree of node 2. You can rebalance the tree by performing a left rotation on node 1; the result is shown on the right side of the figure below.

The LL case is symmetric to the RR case. Draw it out for yourself. You can rebalance the tree by performing a right rotation on the root.

The RL case is illustrated on the left side of the figure below. It occurs when the height of the right subtree of node 1 exceeds the height of the left subtree of node 1 by more than one (as in the RR case), but the left subtree of node 3 is taller than the right subtree of node 3 (unlike the RR case). To handle this case, you perform a right rotation on node 3. The result is shown on the right side of the figure. It's not balanced yet, but it's in the RR configuration, which you can balance using a left rotation. So rebalancing the RL case requires a total of two rotations.

The LR case is symmetric to the RL case. Draw it out for yourself. You can rebalance the tree by performing a left rotation followed by a right rotation.

Your job is to implement balance by recognizing these four cases and performing rotations. You might want to write helper methods for performing the rotations; it's up to you. You do not need to perform any recursion; you just need to balance at a single node, under the assumption that its subtrees have already been balanced.

Write Dictionary Classes

Download the file intdictionary_bstn.py from the course web site. Rename it to intdictionary_avltn.py. Edit it to use AVLTreeNode instead of BinarySearchTreeNode. This requires a few small changes, because the interface of the AVLTreeNode class is not identical to the interface for the BinarySearchTreeNode class. The integer dictionary class should still be IntDictionary, and its methods should work identically to our old IntDictionary's — only more quickly.

Make a copy of your file dictionary_bstn.py from the previous assignment. It uses the integer dictionary based on BinarySearchTreeNode, right? But now we know that unbalanced binary search trees are for losers. Rename the file to dictionary_avltn.py, and edit it to use the integer dictionary based on AVLTreeNode. This should require very few changes. Again, the class should still be called Dictionary, and its methods should work identically to our old Dictionary's, but more quickly.

Moral: The user of a class, method, or function just needs to know what it does (the interface), not how it does it (the implementation). If we're supplying a Dictionary class to our users, then we should be able to change its implementation, as long as we don't change its interface. When the users discover that our new Dictionary is faster than our old one, but doesn't break any of their software, perhaps they will give us a soft, chewy cookie.

Submit Your Work

After testing them thoroughly, submit your three files avltreenode.py, intdictionary_avltn.py, and dictionary_avltn.py electronically as usual. They will be graded according to these criteria: