Я реализую алгоритм 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();
}
Любая помощь или намек были бы оценены, спасибо.
В коде есть много ошибок.
Как показал в своем 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;
}
}
Почти наверняка неограниченная рекурсия. getLeftChild
что это было ошибкой в реализации getLeftChild
или getRightChild
. Я предлагаю вам пройти через отладчик, и я готов поспорить, что вы быстро поймете, где это происходит.
Однако, если у вас очень глубокое дерево, вы можете обнаружить, что исключение является законным, и в этом случае вам нужно будет пересмотреть алгоритм. И традиционная техника хвостовой рекурсии , по-видимому, трудно реализовать на Java.