旋转二叉搜索树

时间:2014-09-30 05:34:47

标签: java rotation binary-tree avl-tree

我正在实现二叉搜索树。如果我发现树不平衡,我已经创建了一种旋转树的方法。不知何故,这种方法无法正常工作,我的树被清空了。我添加的最后两个值使树不平衡仍留在树中。你能告诉我算法有什么问题吗?我没有发布全班,因为它很长,不想混淆任何人。

 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 个答案:

答案 0 :(得分:0)

如果您有这样的错误,那么想象一下做什么总是有帮助的。我已经为您的实施添加了(个人)评论:

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

我已经纠正了你的算法(至少是为了正确的平衡。如果按照我的指导方针,左边的平衡就可以完成)。要创建这样的算法,您可以使用我在下面介绍的技术:

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

(*)这绝不会发生,好像我们平衡,然后右边的树大于左边的树。

要理解算法,记下算法中发生的事情是有帮助的:

首先,我绘制一个这个算法所需的简单树。

  1
 / \
2   3
   / \
  4   5

现在我在算法的每个阶段记下所有指针链接(数字与算法中的数字相对应):

(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

现在我再次把树组成:

    3
   / \
  1   5
 / \
2   4

使用您的算法看起来(数字引用我在算法中插入的数字):

  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

您的算法的结果是:

  3
 / \
4   5

特别是在使用纸和笔时,最好对这种算法进行评估;)