我正在开发的当前项目是开发一个AVL树类。我不是最优秀的程序员,但我确实很清楚这个结构应该如何工作。我的第一个测试案例是RL不平衡,我的树能够正确重组。然而,对于我的LL失衡的下一个测试案例,发生了一些奇怪的事情。我的代码正确地识别了不平衡,它似乎正确地旋转,但是对于最终树,在平衡之前添加的节点被移除并且树恢复到添加节点之前的状态。解释这有点奇怪的问题当然我会提供我的代码。完全有可能我只是在某个地方犯了一个愚蠢的错误,但那些新鲜的眼睛真的会有所帮助。此外,如果有人有任何建议,以改善我的编码实践,将不胜感激,谢谢!
这个类是我为我的课程开发的数据结构库的一部分。我将仅发布此类的代码,但如果有人需要接口/超类,我可以提供它们。
package lib280.tree;
public class AVLTree280<I extends Comparable<? super I>> extends OrderedSimpleTree280<I>{
protected AVLNode280<I> AVLNode280RootLeftChild(){
return (AVLNode280<I>) this.rootNode().leftNode();
}
protected AVLNode280<I> AVLNode280Root(){
return (AVLNode280<I>) this.rootNode();
}
protected AVLNode280<I> AVLNode280RootRightChild(){
return (AVLNode280<I>) this.rootNode().rightNode();
}
protected AVLNode280<I> createNewNode(I x){
return new AVLNode280<I>(x);
}
public AVLTree280<I> rootLeftSubtree(){
return (AVLTree280<I>) super.rootLeftSubtree();
}
public AVLTree280<I> rootRightSubtree(){
return (AVLTree280<I>) super.rootRightSubtree();
}
/** Insert x into the tree. <br>
Analysis : Time = O(log n) worst case, where **/
public void insert(I x,AVLTree280<I> tree)
{
if (tree.isEmpty()){
tree.rootNode = createNewNode(x);
}
else if (x.compareTo(tree.rootItem()) < 0)
{
if(tree.rootNode().leftNode()==null) tree.rootNode().leftNode=createNewNode(x);
else{
insert(x,tree.rootLeftSubtree());
}
tree.AVLNode280Root().setLeftSubTreeHeight((Math.max(tree.AVLNode280RootLeftChild().getRightSubTreeHeight(), tree.AVLNode280RootLeftChild().getLeftSubTreeHeight()))+1);
}
else{
if(tree.rootNode().rightNode()==null) tree.rootNode().rightNode=createNewNode(x);
else{
insert(x,tree.rootRightSubtree());
}
tree.AVLNode280Root().setRightSubTreeHeight((Math.max(tree.AVLNode280RootRightChild().getLeftSubTreeHeight(), tree.AVLNode280RootRightChild().getRightSubTreeHeight()))+1);
}
restoreAVLProperty(tree);
}
protected int balancingFactor(AVLTree280<I> tree){
return tree.AVLNode280Root().getLeftSubTreeHeight()-tree.AVLNode280Root().getRightSubTreeHeight();
}
protected void restoreAVLProperty(AVLTree280<I> tree){
if (balancingFactor(tree) == 2) { //left side
if (balancingFactor(tree.rootLeftSubtree()) == -1) { //reduce left right imbalance to left left
tree.rootNode().leftNode=rotateLeft(tree.AVLNode280RootLeftChild());
}
tree.rootNode=rotateRight(tree.AVLNode280Root());// fix left left imbalance
System.out.println("The tree root node at this point is: " +tree.rootNode().toString());
}
else if(balancingFactor(tree)==-2){ // right side
if (balancingFactor(tree.rootRightSubtree()) == 1) { //reduce right left imbalance to right right
tree.rootNode().rightNode=rotateRight(tree.AVLNode280RootRightChild());
}
tree.rootNode=rotateLeft(tree.AVLNode280Root()); //fix right right imbalance
}
else{
}
}
protected AVLNode280<I> rotateLeft(AVLNode280<I> node){
AVLNode280<I> holder,holder2;
holder=(AVLNode280<I>) node.rightNode();
node.setRightNode(holder.leftNode());
holder.setLeftNode(node);
holder2 = (AVLNode280<I>) node.rightNode();
if(holder2!=null){
node.setRightSubTreeHeight(Math.max(holder2.getLeftSubTreeHeight(),holder2.getRightSubTreeHeight())+1);
}
else{
node.setRightSubTreeHeight(0);
}
holder2 = (AVLNode280<I>) node.leftNode();
if(holder2!=null){
node.setLeftSubTreeHeight(Math.max(holder2.getLeftSubTreeHeight(),holder2.getRightSubTreeHeight())+1);
}
else{
node.setLeftSubTreeHeight(0);
}
holder2=(AVLNode280<I>) holder.rightNode();
if(holder2!=null){
holder.setRightSubTreeHeight(Math.max(holder2.getLeftSubTreeHeight(),holder2.getRightSubTreeHeight())+1);
}
else{
holder.setRightSubTreeHeight(0);
}
holder.setLeftSubTreeHeight(Math.max(node.getLeftSubTreeHeight(),node.getRightSubTreeHeight())+1);
return holder;
}
protected AVLNode280<I> rotateRight(AVLNode280<I> node){
AVLNode280<I> holder,holder2;
holder=(AVLNode280<I>) node.leftNode();
node.setLeftNode(holder.rightNode());
holder.setRightNode(node);
holder2 = (AVLNode280<I>) node.leftNode();
if(holder2!=null){
node.setLeftSubTreeHeight(Math.max(holder2.getLeftSubTreeHeight(),holder2.getRightSubTreeHeight())+1);
}
else{
node.setLeftSubTreeHeight(0);
}
holder2 = (AVLNode280<I>) node.rightNode();
if(holder2!=null){
node.setRightSubTreeHeight(Math.max(holder2.getLeftSubTreeHeight(),holder2.getRightSubTreeHeight())+1);
}
else{
node.setRightSubTreeHeight(0);
}
holder2=(AVLNode280<I>) holder.leftNode();
if(holder2!=null){
holder.setLeftSubTreeHeight(Math.max(holder2.getLeftSubTreeHeight(),holder2.getRightSubTreeHeight())+1);}
else{
holder.setLeftSubTreeHeight(0);
}
holder2=(AVLNode280<I>) holder.rightNode();
if(holder2!=null){
holder.setRightSubTreeHeight(Math.max(node.getLeftSubTreeHeight(),node.getRightSubTreeHeight())+1);
}
else{
holder.setRightSubTreeHeight(0);
}
System.out.println("Holder at this point is: " +holder.toString());
return holder;
}
public void printTreeHeights(AVLNode280<I> node){
if(node==null) return;
System.out.println("left: "+ Integer.toString(node.getLeftSubTreeHeight())+" , "+ "right: "+ Integer.toString(node.getRightSubTreeHeight())+"\n");
printTreeHeights((AVLNode280<I>)node.leftNode());
printTreeHeights((AVLNode280<I>)node.rightNode());
}
/**
* @param args
*/
public static void main(String[] args) {
AVLTree280<Integer> testAVL=new AVLTree280<Integer>();
System.out.println("Test for RL imbalance");
testAVL.insert(5, testAVL);
//System.out.println(testAVL.toString());
testAVL.insert(10, testAVL);
// System.out.println(testAVL.toString());
testAVL.insert(6,testAVL);
//System.out.println(testAVL.toString());
// testAVL.printTreeHeights(testAVL.AVLNode280Root());
System.out.println("-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-");
System.out.println("Test for LL imbalance");
testAVL.insert(1,testAVL);
System.out.println(testAVL.toString());
//testAVL.printTreeHeights(testAVL.AVLNode280Root());
testAVL.insert(0,testAVL);
//testAVL.printTreeHeights(testAVL.AVLNode280Root());
System.out.println(testAVL.toString());
}
}
具有级别顺序遍历的第一种情况的输出是6,5,10
下一个案例使用级别顺序遍历为6,5,10,1。插入0并重新平衡后,树会回到6,5,10。这很奇怪,因为我有一个语句打印重新平衡后要返回的值
此时持有人是:1 此时树根节点为:1
这两个陈述表明LL重新平衡发生但没有正确更新。