旋转二叉搜索树 [英] Rotating a binary search tree

查看:140
本文介绍了旋转二叉搜索树的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在实现一个二进制搜索树.如果发现树不平衡,我已经创建了一种旋转树的方法.不知何故,此方法无法正常工作,我的树被清空了.我添加的使树不平衡的最后两个值仍然保留在树中.你能告诉我我的算法有什么问题吗?我没有发布整个课程,因为它很长,不想让任何人感到困惑.

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

推荐答案

如果您有这样的错误,那么想象完成该操作总是有帮助的.我已向您的实施中添加了(个人)评论:

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

这篇关于旋转二叉搜索树的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆