Search code examples
javarotationred-black-tree

Red-black tree - how to rotate if root is the grandparent?


I am working on writing red-black tree myself. But when I test the rotation that involves root to be rotated, somewhat it loses reference.

Tree structure:

          45             
        /    \
      40x      70        
     /  \     /
    7   41   50           
   / \
  6  39

The rotate logic says: "Rotate with 45(root) as top, in the direction that raises X (i.e. 40)"

So this means right rotate and result should look like:

     40x  
    /   \
   7     45
 / \     / \
 6  39  41  70
           /
          50

Assuming that node 45 is grandparent and 7 is parent and 41 is current. (I know the order doesn't make sense but please ignore, this is because I've rotated once already)

Code:

  //current is node 45
    //parent is node 7
    //grandparent is node 45 (root)

    //first detach cross node (i.e. 41)
    Node crossNode2 = grandparent.left.right;
    grandparent.left.right = null; //detach


                   45             
                /     \
              40x      70        
             /  \      /
            7   null   50           
           / \
          6  39

    grandparent.left = null;




                   45             
                 /    \
               null   70        
                      /
                    50           

    current.right = grandparent;

          40
        /    \
      7        45
     /  \     /  \
   6    39   null 70
                  /
                 50

    grandparent.left = crossNode2; //attach


         40  
        /   \
       7     45
     / \     / \
     6  39  41  70
               /
              50

But somehow this code does not work. When I tested:

preorder
45, 39, 70, 50
breadth-first
45, 39, 70, 50

So I think the result is actually:

  45
 /  \
39  70
     /
    50

Could anyone give me tips what's wrong with my rotation code?


Solution

  • Step to do a right rotation on node Q:

    1. Let P = Q's left child.
    2. Q's left child = P's right child
    3. P replaces Q as its parent's child
    4. P's right child = Q

    You're missing the bolded step in your supplied code. I think your problem is you're treating rotations involving the root node as a special case. Obviously you can't do this if Q is the root and its parent is null. Try creating a "head" node who's right node is the root. This allows rotations involving the root to work using normal algorithms.

    public static void rotateRight(Node node) {
        assert(!node.isLeaf() && !node.left.isLeaf());
        final Node child = node.left;
        node.setLeft(child.right);
        if (node.isRightChild())
             node.parent.setRight(child);
        else node.parent.setLeft(child);
        child.setRight(node);
    }
    

    Node that setRight and setLeft keep the parent reference updated as well as updating right and left. The node.isRightNode() call can be just (node.parent.right == node).