简体   繁体   English

线程“ main”中的异常java.lang.StackOverflowError

[英]Exception in thread “main” java.lang.StackOverflowError

Error received: 收到错误:

Exception in thread "main" java.lang.StackOverflowError
    at AVL.insert(AVL.java:45)

I am not familiar with the error I was given, but I do know that it only happens when the array being used to build the AVL tree is a vary large size and is occurring during insert when moving to the right side of the tree. 我不熟悉给出的错误,但我确实知道,只有在用于构建AVL树的数组的大小很大且在插入树的右侧插入时发生该错误时,才会发生该错误。 I am not sure why this is happening though (in other words I do not know exactly what StackOverflowError is and why it is happening). 我不确定为什么会这样(换句话说,我不确切知道什么是StackOverflowError以及为什么会发生)。

AVL class: AVL类别:

//AVL.java
import java.util.*;
import java.io.*;

public class AVL{
    AvlNode root;

   public void tree(int[] list){
      for(int i=0; i<list.length; i++){
         insertPrep(list[i]);
      }
   }

   public void insertPrep(int data){
      if (root==null){root = new AvlNode(data);}
        else {
         AvlNode newNode = new AvlNode(data);
         root = insert(root, newNode);
         root = rebalance(root);
         adjustHeight(root);
      }
    }

   public AvlNode insert(AvlNode node, AvlNode newNode){
      if (node.key > newNode.key){
         if(node.left!=null){node.left=insert(node.left , newNode);}
         else{node.left=newNode;}
      }
      else if (node.key < newNode.key){
         if(node.right!=null){node.right=insert(node.right, newNode);}
         else{node.right=newNode;}
      }
      AvlNode result = rebalance(node); 
      adjustHeight(result);
      return result;
   }

   public int height (AvlNode node ){
      if (node == null){return 0;}
      else {return node.height;}
   }

   public void adjustHeight (AvlNode node){
      if (root != null){ root.height = 1+ Math.max(height(root.left),height(root.right));}
   }

   public AvlNode rebalance (AvlNode node){
      AvlNode newAvlNode = node;

      if (node.left != null && node.right != null){
        if (node.left.height-node.right.height==2){
            if (node.left.left.height>node.left.right.height){
                AvlNode n2 = node.left;
                AvlNode n3 = node;
                n3.left = n2.right;
                n2.right = n3;

                adjustHeight(n3);
                adjustHeight(n2);
                newAvlNode = n2;
            } else {
                AvlNode n1 = node.left;
                AvlNode n2 = node.left.right;
                AvlNode n3 = node;
                n1.right = n2.left;
                n2.left = n1;
                n3.left = n2.right;
                n2.right = n3;

                adjustHeight(n1);
                adjustHeight(n3);
                adjustHeight(n2);
                newAvlNode = n2;
            }
        } else if (node.right.height-node.left.height==2){
            if (node.right.right.height>node.right.left.height){
                AvlNode n1 = node;
                AvlNode n2 = node.right;
                n1.right = n2.left;
                n2.left = n1;

                adjustHeight(n1);
                adjustHeight(n2);
                newAvlNode = n2;
            } else {
                AvlNode n1 = node;
                AvlNode n2 = node.right.left;
                AvlNode n3 = node.right;
                n1.right = n2.left;
                n2.left = n1;
                n3.left = n2.right;
                n2.right = n3;

                adjustHeight(n1);
                adjustHeight(n3);
                adjustHeight(n2);
                newAvlNode = n2;
            }
        }
      }
    return newAvlNode;
   }

   class AvlNode{
    int key, height; //data for input numbers and height for height of nodes to keep balance
    AvlNode left, right; //left for left side of tree and right for right side of tree

      AvlNode(int data){
         key = data;
      }

   }
}

Class using AVL: 使用AVL的类:

//Tree.java
import java.io.*;
import java.util.*;

public class Tree{

   public static void main(String[] args){

      int n = 30000; //numbers to be in arrays
      int a[] = new int[n]; //first array

      for (int i=0; i<n; i++){
         a[i] = i+1; //insert #'s 1-n; smallest to largest
      }

      //send arrays to be put in AVL trees
      AVL avl = new AVL();
      double timeSoFar = (double)System.nanoTime();
      avl.tree(a);
      double treeTime = (double)System.nanoTime() - timeSoFar;
      printTime('a',treeTime, "AVL");

   }

   public static void printTime(char l, double treeTime, String tree){
      double treeTimeMin = treeTime/600000;
      treeTimeMin/=100000;
      System.out.println("Elapsed time for building " + tree + " " + "Tree for array '" + l + "': " + treeTime + " nanoseconds, or: " + treeTimeMin + " minutes.");
   }

}

Since your array is sorted from smallest to largest, when you try to insert the, say, 15000th node using insertPrep (see the loop in tree() ), you are going to recursively call insert(AvlNode node, AvlNode newNode) 15000 times. 由于数组是从最小到最大排序的,因此当您尝试使用insertPrep插入第15000个节点时(请参见tree()的循环),您将递归调用insert(AvlNode node, AvlNode newNode) 15000次。

This is due to the test in insert 这是由于insert的测试

  if (node.key > newNode.key){
     if(node.left!=null){node.left=insert(node.left , newNode);}
     else{node.left=newNode;}
  }

The recursions are too deep 递归太深

Recursion is probably not your best choice to find the location in the tree and you should resort to a loop which will be more efficient anyway because you do not have to accumulate the frames between the calls. 递归可能不是在树中找到位置的最佳选择,并且您应该诉诸循环,因为无论如何您不必在调用之间累积帧,因此循环将更加高效。

Alternatively, use a language such as Scala that knows about tail recursion and automatically unfolds tail recursions to loops at compile time. 或者,使用诸如Scala之类的语言了解尾递归,并在编译时自动将尾递归展开为循环。

EDIT The explanation for the Overflow is probably over simplistic. 编辑溢出的解释可能过于简单。 See comments below 见下面的评论

I think there is something wrong with re-balancing. 我认为重新平衡存在问题。

You are doing 你在做

AvlNode result = rebalance(node); 
adjustHeight(result);

which looks weird to me because you should adjust the height first then re-balance then adjust height again. 这对我来说很奇怪,因为您应该先调整高度,然后重新平衡,然后再调整高度。 Looks like re-balancing never happened because height is never updated; 似乎从未发生过重新平衡,因为从未更新过高度。 hence, your tree will be very high; 因此,你的树会很高。 hence, the stack overflow exception. 因此,堆栈溢出异常。

I am not 100% certain, but that looks like the problem. 我不是100%肯定的,但是看起来像是问题所在。 One sanity check you can do is to create, say, 100 nodes and check if your tree is balanced. 您可以做的一项健全性检查是创建100个节点,并检查树是否平衡。 If not, you didn't implement the balancing properly. 如果没有,则说明您没有正确实现平衡。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 “线程”main“java.lang.StackOverflowError 中的异常” - “Exception in thread ”main“ java.lang.StackOverflowError” 线程“main”java.lang.StackOverflowError中的异常 - Exception in thread “main” java.lang.StackOverflowError 线程“main”java.lang.StackOverflowError中的异常 - Exception in thread “main” java.lang.StackOverflowError 这在Java中 - 线程“main”java.lang.StackOverflowError中的异常 - This in Java - Exception in thread “main” java.lang.StackOverflowError Java-递归-线程“ main”中的异常java.lang.StackOverflowError - Java - Recursion - Exception in thread “main” java.lang.StackOverflowError QuickSort在线程“ main”中给出异常java.lang.StackOverflowError - QuickSort giving exception in thread “main” java.lang.StackOverflowError 线程“ main”中的异常java.lang.StackOverflowError actionListeners - Exception in thread “main” java.lang.StackOverflowError actionListeners 线程“ main”中的异常:java.lang.StackOverflowError,为什么? - Exception in thread “main”: java.lang.StackOverflowError,Why? 递归-线程“ main”中的异常java.lang.StackOverflowError - Recursion - Exception in thread “main” java.lang.StackOverflowError 线程“ main”中的异常java.lang.StackOverflowError问题 - Exception in thread “main” java.lang.StackOverflowError issue
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM