Rotating a binary search tree

有些话、适合烂在心里 提交于 2019-12-08 10:52:07

问题


I am implementing a binary search tree. I have created a method to rotate the tree if I find that the tree is out of balance. Somehow this method is not working correctly and my tree is emptied. Only the last two values I added to make the tree unbalanced are still left in the tree. Can you tell me what is wrong with my algorithm? I have not posted the entire class because it is very long and do not want to confuse anyone.

 public boolean balanceBST(){
      if (root == null){
          return false;
      }

      int right = treeHeight(root.right);
      int left = treeHeight(root.left);

      if (nodeBalanceLevel(root) > 1){

                if (right - left > 1){
                    this.balanceRight();
        }
        if ( left - right > 1){
        this.balanceLeft(); 
        }
        return balanceBST();  

      }

    return true;

  }

  private void balanceRight(){

            TreeNode oldRoot = root;
            if (root.left != null)
            oldRoot.left = root.left;
            if (root.right != null)
            root = root.right;
            if (root.left != null)
             oldRoot.right = root.left; 
  }

  public void balanceLeft(){
      TreeNode oldRoot = root;
      if (root.right != null)
      oldRoot.right = root.right;
      if (root.left != null)
      root = root.left;
      if (root.right != null)
       oldRoot.left = root.right;   
  }

回答1:


If you have such a bug then it is always helpful to imagine what is done. I've added (personal) comments to you implementation:

private void balanceRight() {
  TreeNode oldRoot = root;     // Save the current root (1)
  if (root.left != null)       // This does not matter as first an assignment of null does not matter
                               // second the next assignment is a NoOp
    oldRoot.left = root.left;  // this is an assignment with no effect (2)
  if (root.right != null)
    root = root.right;         // Setting the new root (3)
  if (root.left != null)       // Now root.left is the left part of the previous root.right
                               // the left part of the previous root is discarded this way
    oldRoot.right = root.left; // oldRoot will be invalid after this operation therefore it does not matter (4)
}

I've corrected your algorithm (at least for the right balancing. The left balancing can be done by you if you follow my guidelines). To create such an algorithm you can use a technique that I introduce in the following:

private void balanceRight() {
  TreeNode oldRoot = root;     // Save the current root (1)
  if (root.right != null) {    // Can this ever happen? (*)
    root = root.right;         // Setting the new root  (2)
  }
  oldRoot.right = root.left; // Assign the left sub tree to the previous root right tree (3)
  root.left = oldRoot;       // Assign to the new left tree the prevouis left tree (4)
}

(*) This should never happen as if we balance right then the right tree is larger than the left one.

To understand the algorithm it is helpful to write down what happens in the algorithm:

First I draw a tree that is as simple as needed for this algorithm.

  1
 / \
2   3
   / \
  4   5

Now I write down all pointers link at every stage of the algorithm (the numbers correspondent with the numbers in the algorithm):

(1)

root    -> 1 / left -> 2 / right -> 3
oldRoot -> 1 / left -> 2 / right -> 3

(2)

root    -> 3 / left -> 4 / right -> 5
oldRoot -> 1 / left -> 2 / right -> 3

(3)

root    -> 3 / left -> 4 / right -> 5
oldRoot -> 1 / left -> 2 / right -> 4

(4)

root    -> 3 / left -> 1 / right -> 5
oldRoot -> 1 / left -> 2 / right -> 4

Now I compose the tree back again:

    3
   / \
  1   5
 / \
2   4

With your algorithm it looks like (the numbers reference to the numbers I inserted in your algorithm):

  1
 / \
2   3
   / \
  4   5

(1)

root    -> 1 / left -> 2 / right -> 3
oldRoot -> 1 / left -> 2 / right -> 3

(2)

root    -> 1 / left -> 2 / right -> 3
oldRoot -> 1 / left -> 2 / right -> 3

(3)

root    -> 3 / left -> 4 / right -> 5
oldRoot -> 1 / left -> 2 / right -> 3

(4)

root    -> 3 / left -> 4 / right -> 5
oldRoot -> 1 / left -> 2 / right -> 4

The result of your algorithm is then:

  3
 / \
4   5

Especially such algorithm can be evaluated at best when using paper and pencil ;)



来源:https://stackoverflow.com/questions/26113441/rotating-a-binary-search-tree

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!