Section 4 - Implementing Rotation

5A.4.1 Single Rotation

It is with mixed emotions that I provide you with, or refer you to, code that does rotations. Writing and debugging this kind of code is what turns you into strong, capable programmers. On the other hand, I know that you don't have unlimited time, and cannot write all the functions on your own. So I've decided to give you the code here, with the understanding that you will compare it scrupulously with the rules and pictures that came before and make sure you agree that it does what it should. Also, I'll give you a chance to do some implementation coding in your homework assignment.

The pictures and rules are in the previous pages, and I have kept the names like k1 and k2 as before, using k2 as the center of a single rotation, and k1 as its left or right child. As usual, I am giving you an implementation which presumes the template prototype is declared, above. I have not yet shown you that prototype, because there are some other things to say before I reveal the big picture.

Single Left Rotation

template <class Comparable>
void FHavlTree<Comparable>::rotateWithLeftChild( FHs_treeNode<Comparable> * & k2 )
{
   FHs_treeNode<Comparable> *k1 = k2->lftChild;
   k2->lftChild = k1->rtChild;
   k1->rtChild = k2;
   k2->setHeight( max( heightOf(k2->lftChild),  heightOf(k2->rtChild) ) + 1 );
   k1->setHeight( max( heightOf(k1->lftChild),  k2->getHeight() ) + 1 );
   k2 = k1;
}

Anomalies to ignore for now:

Things to observe:

Single Right Rotation

Here is the companion method:

template <class Comparable>
void FHavlTree<Comparable>::rotateWithRightChild( FHs_treeNode<Comparable> * & k2 )
{
   FHs_treeNode<Comparable> *k1 = k2->rtChild;
   k2->rtChild = k1->lftChild;
   k1->lftChild = k2;
   k2->setHeight( max( heightOf(k2->lftChild), heightOf(k2->rtChild) ) + 1 );
   k1->setHeight( max( heightOf(k1->rtChild), k2->getHeight() ) + 1 );
   k2 = k1;
}

5A.4.2 Double Rotation

Because double rotation was simply the composition of two single rotations, the coding for this esoteric maneuver is dramatically simple:

template <class Comparable>
void FHavlTree<Comparable>::doubleWithLeftChild( FHs_treeNode<Comparable> * & k3 )
{
   rotateWithRightChild(k3->lftChild);
   rotateWithLeftChild(k3);
}

Hidden in the streamlined logic is the fact that k2, the center of the first of the two rotations, does not have to be named, explicitly -- it is, after all, just k3->lftChild. The association with k2 comes by looking at the formal parameter name in rotateWithRightChild().

Here is the companion:

template <class Comparable>
void FHavlTree<Comparable>::doubleWithRightChild( FHs_treeNode<Comparable> * & k3 )
{
   rotateWithLeftChild(k3->rtChild);
   rotateWithRightChild(k3);
}

The coding for these methods is deceptively simple. It belies the careful design and debugging needed to go into the class as a whole, leading to the details in the bullets above. Why use FHs_treeNodes instead of AvlNodes? Why uses accessors for the public member height? You'll see the reasons, but it isn't quite the same as doing it yourself. That's why I want to encourage you to at least master the logic here, and when we get to the next phase of implementation, likewise, study every move, asking me if you have any questions.

You may even be able to find improvements to my code, which I would celebrate, with a fine bottle of Pinot AVL.