views:

57

answers:

2

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?

+3  A: 

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).

Gunslinger47
Thanks for the tip!
masato-san
A: 

Based on Gunslinger47's answer, I've tested left rotation version too. The code works fine. (please do let me know if not..)

Also documented on my website :)

http://masatosan.com/btree.jsp

public static void rotateLeft(Node node) {
    assert(!node.isLeaf() && !node.right != null);
    final Node child = node.right;
    node.setRight(child.left);
    if(node.isLeftChild()) {
        node.parent.setLeft(child);
    }
    else {
        node.parent.setRight(child);
    }
    chlid.setLeft(node);
}
masato-san