Java 尝试实现AVL树的旋转时出现堆栈溢出

Java 尝试实现AVL树的旋转时出现堆栈溢出,java,avl-tree,Java,Avl Tree,每次我向树中添加一个新节点时,它首先将其作为二叉树排序,然后在AVL中递归查找冲突 问题是在我的rotate函数中,我试图测试AVL冲突,它需要左-左旋转,当我这样做时,首先创建一个根,然后创建一个右子a,然后创建a的另一个左子b。现在发生的是,它输出到最后,然后我得到一个错误,说: 线程“main”java.lang.StackOverflowerr中出现异常 位于AVLTree$AVLNode.height(AVLTree.java:63) 位于AVLTree$AVLNode.height(

每次我向树中添加一个新节点时,它首先将其作为二叉树排序,然后在AVL中递归查找冲突

问题是在我的rotate函数中,我试图测试AVL冲突,它需要左-左旋转,当我这样做时,首先创建一个根,然后创建一个右子a,然后创建a的另一个左子b。现在发生的是,它输出到最后,然后我得到一个错误,说:

线程“main”java.lang.StackOverflowerr中出现异常

位于AVLTree$AVLNode.height(AVLTree.java:63)

位于AVLTree$AVLNode.height(AVLTree.java:62)

我真的不明白这个问题

54 int getBalance(){
55       int leftHeight = (left == null)?0:left.height();
56       int rightHeight = (right == null)?0:right.height();
57       
58       return leftHeight - rightHeight;
59   }
61 int height(){
62      int leftHeight = (left == null)?0:left.height();
63      int rightHeight = (right == null)?0:right.height();

        return 1 + Math.max(leftHeight, rightHeight);
    }    

public void rotate(AVLNode test){
        System.out.println(test.getBalance());
        if(Math.abs(test.getBalance()) < 2){

            if(test.getParent() != null){
                rotate(test.getParent());
            }
            else{
                return;
            }
        }
        if(test.getBalance() <= -2){

            System.out.println(test.getBalance());

            if(test.getRight().getBalance() <= 0){

                System.out.println("i'm in");
                AVLNode parent = test.getParent();

                if(parent != null){

                    if(parent.getLeft() == test){
                        parent.setLeft(test.getRight());
                    }
                    else{
                        parent.setRight(test.getRight());
                    }
                }

                else{
                    this.root = test.getRight();
                }
                test.setParent(test.getRight());

                if(test.getRight().getLeft() != null){

                test.getRight().getLeft().setParent(test);
                test.setRight(test.getRight().getLeft());
                }

                test.getParent().setLeft(test);
                System.out.println("got till the end");
            }
        }
54 int getBalance(){
55 int leftHeight=(left==null)?0:left.height();
56 int rightHeight=(right==null)?0:right.height();
57
58返回左高-右高;
59   }
61国际高度(){
62 int leftHeight=(left==null)?0:left.height();
63 int rightHeight=(right==null)?0:right.height();
返回1+数学最大值(leftHeight,rightHeight);
}    
公共空隙旋转(AVLNode测试){
System.out.println(test.getBalance());
if(Math.abs(test.getBalance())<2){
if(test.getParent()!=null){
旋转(test.getParent());
}
否则{
返回;
}
}
if(test.getBalance()


left
不是
null
时,此
递归方法
没有
退出
,它将调用left.height()left.height()left.height()left.height()……直到堆栈溢出

我认为您的
旋转
方法有问题,尽管仅仅通过读取代码很难调试。在我看来,您得到的是一个循环引用,这会导致
高度
方法中的堆栈溢出。尽管根据sta,发生溢出的地方是
高度
ck trace,除非树结构中有循环,否则不应该发生。例如,如果其中一个节点将自身作为左子节点,则会发生这种情况

我对AVL算法不是很熟悉,但在我看来,
rotate
方法中的一个错误源(可能不是唯一的一个)是,
parent
的左子级可能会设置为
test
的右子级,但test的右子级的父级永远不会设置为
parent


同样,像这样的代码很难阅读和调试。建议尝试将算法分成更小的块,或者制作易于验证的小辅助函数。

我的想法是,如果我们需要计算节点的高度,那么就计算其左子节点和右子节点的高度
返回1+Math.max(leftHeight,rightHeight)

完整的代码如下所示:

  int height(TreeNode tn){ 
      if(tn==null){return 0;}
      int leftHeight = tn.left.height();
      int rightHeight = tn.right.height();
      return 1 + Math.max(leftHeight, rightHeight);
  }

您建议如何退出该方法?我的想法是,如果需要计算节点的高度,则计算其左子节点和右子节点的高度,然后
返回1+Math.max(leftHeight,rightHeight)完整的代码可以是这样的:'int height(TreeNode tn){if(tn==null){return 0;}
int leftHeight=tn.left.height();
int righthheight=tn.right.height();
return 1+Math.max(leftHeight,righthheight);
}'假设height是属于AVLNode的方法,在这种情况下,递归调用应该最终终止,假设树结构正确。虽然这是发生溢出的方法,但不是问题的原因。@Lidae我不这么认为。如果left不为null,它将递归调用left.height(),左节点是它自己的,而不是它的左子节点。因此它不会退出。@cainiaofei我从代码的其余部分推断,但似乎每个AVLNode都包含另一个名为“left”的AVLNode。因此递归将成为node.height()->node.left.height()->node.left.left.height()如果它的结构是一棵树,就不会有循环,这个方法最终会终止。你是对的,我真的用了旋转法,我会努力使它更清晰
  int height(TreeNode tn){ 
      if(tn==null){return 0;}
      int leftHeight = tn.left.height();
      int rightHeight = tn.right.height();
      return 1 + Math.max(leftHeight, rightHeight);
  }