Ошибка Stackoverflow при рекурсивном поиске в дереве

1

Я реализую алгоритм Shannon/Fano с использованием Java, и делаю это, вычисляя частоты символов в текстовом файле, после чего я помещаю все эти значения в дерево. Проблема в том, что когда я ищу определенный символ в дереве, я также должен обновить код соответствующего символа (например, если я иду влево, добавлю 0, в противном случае - 1) и делая это рекурсивно, я получаю ошибку stackoverflow. Ниже мой код:

private String getNodeValue(Node node, String symbol) {
    if (node.getLeftChild() != null) {
        if (node.getLeftChild().getData().equalsIgnoreCase(symbol)) {
            node.updateCode(0);
            return node.getData() + "";
        }
    } else if (node.getRightChild() != null) {
        if (node.getRightChild().getData().equalsIgnoreCase(symbol)) {
            node.updateCode(1);
            return node.getData() + "";
        }
    }


    Node nextLeftNode = node.getLeftChild().getLeftChild();
    if (nextLeftNode != null) {
        getNodeValue(nextLeftNode, symbol);
    }

    Node nextRightNode = node.getRightChild().getRightChild();
    if (nextRightNode != null) {
        getNodeValue(nextRightNode, symbol);
    }

    // if symbol is not found return null
    return null;
}

и ошибка stackoverflow запускается в самой первой строке метода, когда имеет место вызов node.getData(). Это моя трассировка стека:

Exception in thread "main" java.lang.StackOverflowError
at ro.uvt.it.datastractures.Node.getData(Node.java:47)
at ro.uvt.it.datastractures.Node.getData(Node.java:47)
at ro.uvt.it.datastractures.Node.getData(Node.java:47)

И это мой метод getData():

public String getData() {
    return this.getData();
}

Любая помощь или намек были бы оценены, спасибо.

Теги:
recursive-datastructures
tree

2 ответа

1
Лучший ответ

В коде есть много ошибок.

Как показал в своем StackTrace, бесконечная рекурсия в getData метод, а не в getNodeValue методе, так что вам нужно опубликовать исходный код getData метода.

Но метод getNodeValue имеет множество ошибок.

Ваши первые два оператора if имеют точно такое же условие:

if (node.getData().equalsIgnoreCase(symbol)) {

а также

else if (((String) node.getData()).equalsIgnoreCase(symbol)) {

возвраты внутри этих операторов if добавляют пустую строку к результату getData(), который уже возвращает String. Замените каждый из них:

return node.getData();

это просто другой способ писать то же самое, поскольку getData() уже возвращает String, поэтому повторное использование String снова не имеет значения.

Ваши следующие утверждения if рекурсивно вызывают getNodeValue на leftChild и rightChild, но они никогда ничего не возвращают, поэтому вы всегда возвращаете null в свой код, как только вы пройдете первые два идентичных оператора if в своем методе.

Вы, вероятно, должны читать код:

if (node.getLeftChild() != null) {
    String found = getNodeValue(node.getLeftChild(), symbol);
    if (found != null) {
        return found;
    }
}
if (node.getRightChild() != null) {
    String found = getNodeValue(node.getRightChild(), symbol);
    if (found != null) {
        return found;
    }
}
  • 0
    Ваше предложение сработало для меня. Спасибо
  • 0
    @Costy Переполнение стека происходит от this.getData (); в вашей функции getData. По сути, он вызывает сам себя, а не возвращает какие-либо данные. Приведенный выше код работает только потому, что вы больше не вызываете getData, но, пожалуйста, удалите эту функцию, так как она вызовет тот же самый stackOverflow при следующем вызове.
Показать ещё 3 комментария
0

Почти наверняка неограниченная рекурсия. getLeftChild что это было ошибкой в реализации getLeftChild или getRightChild. Я предлагаю вам пройти через отладчик, и я готов поспорить, что вы быстро поймете, где это происходит.

Однако, если у вас очень глубокое дерево, вы можете обнаружить, что исключение является законным, и в этом случае вам нужно будет пересмотреть алгоритм. И традиционная техника хвостовой рекурсии , по-видимому, трудно реализовать на Java.

Ещё вопросы

Сообщество Overcoder
Наверх
Меню