我正在实现二叉搜索树。如果我发现树不平衡,我已经创建了一种旋转树的方法。不知何故,这种方法无法正常工作,我的树被清空了。我添加的最后两个值使树不平衡仍留在树中。你能告诉我算法有什么问题吗?我没有发布全班,因为它很长,不想混淆任何人。
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;
}
答案 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
特别是在使用纸和笔时,最好对这种算法进行评估;)