在Java中遍历二进制搜索树时出现StackOverflowerError

在Java中遍历二进制搜索树时出现StackOverflowerError,java,recursion,binary-search-tree,Java,Recursion,Binary Search Tree,我有一个返回BST中最深节点的方法。我有一个引发StackOverflow错误的代码: public int getDeepestNode(AvlNode head) { if (head == null) { return 0; } else { return (Math.max(getDeepestNode(head.getLeftNode()), getDeepestNode(head.getRightNode())) + 1); }

我有一个返回BST中最深节点的方法。我有一个引发StackOverflow错误的代码:

public int getDeepestNode(AvlNode head) {
    if (head == null) {
        return 0;
    } else {
        return (Math.max(getDeepestNode(head.getLeftNode()), getDeepestNode(head.getRightNode())) + 1);
    }
}

在我看来,它看起来不错,为什么会引发错误?

GetDeepTestNode必须在堆栈上重复出现

在AVL树中很可能有一个循环。命名为
head
,可能已经是不洁思想的标志。调试有帮助。 或者,您可以将代码硬化为:

public int getDeepestNode(AvlNode head) {
    return getDeepestNodeSafe(head, new ArrayList<AvlNode>());
}

public int getDeepestNodeSafe(AvlNode head, List<AvlNode> pathFromRoot) {
    if (head == null) {
        return 0;
    } else {
        if (pathFromRoot.contains(head)) {
            StringBuilder sb = new StringBuilder("Cycle: ");
            for (AvlNode node : pathFromRoot) {
                if (node == head) {
                   sb.append("***");
                }
                sb.append(node).append("; ");
            }
            Logger.getLogger(getClass().getName()).log(Level.WARN, sb.toString());
            return 0;
        }
        pathFromRoot.add(head);
        int depth = Math.max(getDeepestNodeSafe(head.left, pathFromRoot),
                             getDeepestNodeSafe(head.right), pathFromRoot) + 1;
        pathFromRoot.remove(pathFromRoot.size() - 1); // Undo
        return depth;
    }
}
public int getDeepestNode(AvlNode头){
返回getDeepestNodeSafe(head,newArrayList());
}
public int getDeepestNodeSafe(AvlNode head,列表路径fromroot){
if(head==null){
返回0;
}否则{
if(pathFromRoot.contains(head)){
StringBuilder sb=新StringBuilder(“循环:”);
for(AvlNode节点:pathFromRoot){
如果(节点==头部){
某人加上“***”号;
}
sb.append(node.append(“;”);
}
Logger.getLogger(getClass().getName()).log(Level.WARN,sb.toString());
返回0;
}
pathFromRoot.add(head);
int depth=Math.max(getDeepestNodeSafe(head.left,pathFromRoot),
getDeepestNodeSafe(head.right),pathFromRoot)+1;
pathFromRoot.remove(pathFromRoot.size()-1);//撤消
返回深度;
}
}

抛出一个非法状态异常肯定会更好,但是使用这段代码,您可能会发现错误更快(或者更快)。

GetDeepTestNode必须在堆栈上重复出现

在AVL树中很可能有一个循环。命名为
head
,可能已经是不洁思想的标志。调试有帮助。 或者,您可以将代码硬化为:

public int getDeepestNode(AvlNode head) {
    return getDeepestNodeSafe(head, new ArrayList<AvlNode>());
}

public int getDeepestNodeSafe(AvlNode head, List<AvlNode> pathFromRoot) {
    if (head == null) {
        return 0;
    } else {
        if (pathFromRoot.contains(head)) {
            StringBuilder sb = new StringBuilder("Cycle: ");
            for (AvlNode node : pathFromRoot) {
                if (node == head) {
                   sb.append("***");
                }
                sb.append(node).append("; ");
            }
            Logger.getLogger(getClass().getName()).log(Level.WARN, sb.toString());
            return 0;
        }
        pathFromRoot.add(head);
        int depth = Math.max(getDeepestNodeSafe(head.left, pathFromRoot),
                             getDeepestNodeSafe(head.right), pathFromRoot) + 1;
        pathFromRoot.remove(pathFromRoot.size() - 1); // Undo
        return depth;
    }
}
public int getDeepestNode(AvlNode头){
返回getDeepestNodeSafe(head,newArrayList());
}
public int getDeepestNodeSafe(AvlNode head,列表路径fromroot){
if(head==null){
返回0;
}否则{
if(pathFromRoot.contains(head)){
StringBuilder sb=新StringBuilder(“循环:”);
for(AvlNode节点:pathFromRoot){
如果(节点==头部){
某人加上“***”号;
}
sb.append(node.append(“;”);
}
Logger.getLogger(getClass().getName()).log(Level.WARN,sb.toString());
返回0;
}
pathFromRoot.add(head);
int depth=Math.max(getDeepestNodeSafe(head.left,pathFromRoot),
getDeepestNodeSafe(head.right),pathFromRoot)+1;
pathFromRoot.remove(pathFromRoot.size()-1);//撤消
返回深度;
}
}

抛出一个IllegalStateException肯定会更好,但是使用这段代码,您可能会更快(或更快)发现错误。

您的BST很可能有一个循环,即左或右节点之一指向树中较高的节点。或者你的树很不平衡,很深。@Codo…或者其他方法中的一个有问题。也应该发布它们,即
getLeftNode()
getRightNode()
。您应该首先至少进行一次基本检查,以查看您的树正在遍历什么。在例程的顶部插入一个简单的print语句来跟踪执行:print head。如果打印它的值,可能更容易阅读。这将使您很容易看到是否在树中发现了循环、代码中缺少适当的递归或其他问题。您的BST很可能有一个循环,即左或右节点之一指向树中较高的节点。或者你的树很不平衡,很深。@Codo…或者其他方法中的一个有问题。也应该发布它们,即
getLeftNode()
getRightNode()
。您应该首先至少进行一次基本检查,以查看您的树正在遍历什么。在例程的顶部插入一个简单的print语句来跟踪执行:print head。如果打印它的值,可能更容易阅读。这将让您非常容易地看到是否在树中发现了循环、代码中缺少适当的递归,或者可能存在其他问题。