【问题标题】:How to fix Stack Overflow from recursive getHeight method如何从递归 getHeight 方法修复堆栈溢出
【发布时间】:2019-04-29 10:25:26
【问题描述】:

当我为计算二叉搜索树高度的方法运行代码时,会导致堆栈溢出错误,但仅适用于具有多个节点的树(我的程序中的 BSTElements)。我读到这是由于错误的递归调用,但无法在我的代码中识别问题。

public int getHeight() {

    return getHeight(this.getRoot());
}

private int getHeight(BSTElement<String,MorseCharacter> element) {

    int height=0;

    if (element == null) {
        return -1;
    }

    int leftHeight = getHeight(element.getLeft());
    int rightHeight = getHeight(element.getRight());

    if (leftHeight > rightHeight) {
        height = leftHeight;
    } else {
        height = rightHeight;
    }

    return height +1;
}

这里是完整的代码:

public class MorseCodeTree {

private static BSTElement<String, MorseCharacter> rootElement;



public BSTElement<String, MorseCharacter> getRoot() {
    return rootElement;
}

public static void setRoot(BSTElement<String, MorseCharacter> newRoot) {
    rootElement = newRoot;
}



public MorseCodeTree(BSTElement<String,MorseCharacter> element) {
    rootElement = element;
}

public MorseCodeTree() {
    rootElement = new BSTElement("Root",  "", new MorseCharacter('\0', null));
}
    public int getHeight() {

    return getHeight(this.getRoot());
}

private int getHeight(BSTElement<String,MorseCharacter> element) {

    if (element == null) {
        return -1;
    } else {
        int leftHeight = getHeight(element.getLeft());
        int rightHeight = getHeight(element.getRight());


    if (leftHeight < rightHeight) {
        return rightHeight + 1;
    } else {
        return leftHeight + 1;
    }
    }
}
public static boolean isEmpty() {
        return (rootElement == null);   
}

public void clear() {
    rootElement = null;
}

public static void add(BSTElement<String,MorseCharacter> newElement) {

        BSTElement<String, MorseCharacter> target = rootElement;
        String path = "";
        String code = newElement.getKey();

        for (int i=0; i<code.length(); i++) {
            if (code.charAt(i)== '.') {
                if (target.getLeft()!=null) {
                    target=target.getLeft();
                } else {
                    target.setLeft(newElement);
                    target=target.getLeft();
                }

            } else {
                if (target.getRight()!=null) {
                    target=target.getRight();
                } else {
                    target.setRight(newElement);
                    target=target.getRight();
                }   
            }
        }
        MorseCharacter newMorseChar = newElement.getValue();

        newElement.setLabel(Character.toString(newMorseChar.getLetter()));
        newElement.setKey(Character.toString(newMorseChar.getLetter()));
        newElement.setValue(newMorseChar);

}

    public static void main(String[] args) {
    MorseCodeTree tree = new MorseCodeTree();
        BufferedReader reader;

    try {
        reader = new BufferedReader(new FileReader(file));
        String line = reader.readLine();


        while (line != null) {

            String[] output = line.split(" ");
            String letter = output[0];
            MorseCharacter morseCharacter = new MorseCharacter(letter.charAt(0), output[1]);

            BSTElement<String, MorseCharacter> bstElement = new BSTElement(letter, output[1], morseCharacter);

            tree.add(bstElement);

            line = reader.readLine();

            System.out.println(tree.getHeight());
        }
        reader.close();




    } catch (IOException e) {
    System.out.println("Exception" + e);
    }

【问题讨论】:

  • 你的叶子节点是null吗?
  • 请显示错误。
  • @ChrisGong 他们不应该这样,有没有办法在我的代码中处理这种可能性?
  • @jen 如果叶节点不为空,那么您的函数将如何终止?
  • 代码看起来不错;元素是否有可能(直接或间接)引用自身?

标签: java recursion stack-overflow


【解决方案1】:

您向我们展示的代码似乎没有任何明显错误1

如果此代码为一棵小树提供StackOverflowException,那很可能意味着您的树创建不正确并且其中有一个循环(循环)。如果您的递归算法在“树”中遇到循环,它将循环直到堆栈溢出2

为了确定这一诊断,我们需要查看一个 MVCE,其中包含构建展示该行为的示例树所需的所有代码。


1 - 高度计算中可能存在“off by one”错误,但这不会导致堆栈溢出。

2 - 当前的 Java 实现不进行尾调用优化。

【讨论】:

  • 我已经用完整的代码更新了我的帖子。这会是我的 add 方法的问题吗?
  • 有可能。尝试使用调试器或“橡皮鸭”调试技术:rubberduckdebugging.com
  • 但是这里有个提示:你有很多方法和字段不应该是static。这是一个糟糕的设计,可能是您的问题的根本原因。首先,由于 rootElementstatic,因此您的应用程序中实际上只有一棵树。
猜你喜欢
  • 1970-01-01
  • 2013-06-16
  • 2017-08-26
  • 2020-07-13
  • 2015-04-04
  • 2017-01-20
  • 2018-12-02
  • 2017-09-06
  • 2019-07-08
相关资源
最近更新 更多