Я новичок в использовании рекурсии для своих методов. Я стараюсь держаться от них подальше по целому ряду причин. Однако для проекта проще использовать рекурсивный метод вместо циклического, поскольку я пытаюсь выполнить обход в глубину для графа.
Поскольку я не слишком хорошо разбираюсь в рекурсии, я не понимаю, почему я получаю следующую ошибку.
This method must return a result of type LinkedList.Node
Код, который у меня есть в настоящее время:
public Node DFSTime(Node node){
if (node == null){
System.out.println("No path found");
return null;
}
else if (node.element.equals(destinationAirport)){
return node;
}
else{
stack.push(node);
DFSTime(node.nextNode);
}
}
Это незаконченный код, так как мне все еще нужно реализовать некоторую логику, однако я не понимаю, как устранить ошибку. Есть ли что-то очень простое, чего мне не хватает?
Обратите внимание, что вы не должны использовать null в качестве контрольного значения, чтобы указать на отсутствие результата. Вместо этого вы должны использовать класс Optional. Приводит к пустому опциону, если он не найден, и к опциону, заполненному узлом, если он найден.
Прямо сейчас ваш случай else просто пытается найти место назначения на следующем узле, но вы ничего не делаете с результатом этого поиска. Вы просто выбрасываете его выводы. Переосмыслите, что вы хотите вернуть в своем другом случае. Подсказка: это, вероятно, то, что возвращает другой поиск, который вы запускаете здесь...
Я думал об использовании стека для отслеживания пути, по которому я шел по графу. И поскольку это атрибут класса, в котором я реализовал DFS. Так что мне не нужно использовать рекурсию, поскольку я ничего не буду делать с результатами рекурсивного метода?
Вы не понимаете. Ваш код не делает то, что вы хотели. Это похоже на то, как вы отправляете своего друга в супермаркет, чтобы купить яйца, но когда он возвращается, вы просто бросаете яйца прямо в мусорное ведро, а затем жалуетесь, почему никто не принес вам яйца. Прямо сейчас вы запускаете рекурсию, но когда она возвращается с результатом, вы отбрасываете результат. Вместо того, чтобы возвращать его и из вашего метода, в результате...




У вас должен быть оператор return по умолчанию в конце функции после закрытия else.
Просто нормальный return null должен работать, верно?
Не обязательно. Зависит от логики, которую вы хотите создать.
@Забузард Видим?
Подробности читайте в других моих комментариях.
Да, и вы, вероятно, захотите что-то сделать с «DFSTime (node.nextNode)», например. вернуть DFSTime (узел. следующий узел);
В условных блоках методов (if-else) вам нужно убедиться, что вы возвращаете соответствующий тип из всех условных операторов, чтобы не было ошибки времени компиляции. В вашем случае блок else рекурсивно вызывает DFSTime(..), ничего не возвращая.
Возможно, вы захотите вернуть ссылку, которая вызывается через рекурсивный вызов, как показано ниже:
public Node DFSTime(Node node){
if (node == null){
System.out.println("No path found");
return null;
}
else if (node.element.equals(destinationAirport)){
return node;
}
else{
stack.push(node);
Node node = DFSTime(node.nextNode);
return node;
}
}
Причина ошибки компиляции довольно тривиальна. Компилятор ясно говорит, что не обеспечил возврат результата для всех возможных случаев.
Тем важнее то, что ваш текущий подход — не верно.
it seems to easier to have a recursive method instead of a looping one since I am trying to do Depth First Traversal for a Graph
Есть важные вещи, которые следует учитывать:
Поле nextNode очень подозрительно. Если каждый Node содержит ссылку, указывающую только на один узел, фактически созданная вами структура данных по определению является не График, а Односвязный список. И нет смысла реализовывать DFS для списка. Каждый узел должен указывать на коллекция узлов, а не на один узел.
Вы должны как-то различать непосещенные узлы и узлы, которые являются уже посетил. Или же вы могли бы и с бесконечной рекурсией. Для этого вы можете определить поле booleanisVisited внутри Node или поместить каждый посещаемый узел в HashSet.
Поскольку вы решили создать рекурсивную реализацию DFS, вам не необходимо создать файл куча. Это требуется только для итеративной реализации.
Не злоупотребляйте глобальными переменными. Я думаю, вы, возможно, захотите проверить, можно ли добраться до разных аэропортов назначения без повторного создания графа.
Используйте геттеры и сеттеры вместо прямого доступа к полям. Это предпочтительная практика в Java.
Ваш метод может выглядеть так (не обязательно, чтобы element был типа String, это просто иллюстрация общей идеи):
public Node DFSTime(Node node, String destinationAirport){
if (node == null || node.isVisited()) {
return null;
}
if (node.getElement().equals(destinationAirport)) {
System.out.println("The destination airport was found");
return node;
}
node.setVisited(true);
for (Node neighbour: node.getNeighbours()) {
Node result = DFSTime(neighbour, destinationAirport);
if (result != null) return result;
}
return null;
}
И узел может выглядеть так:
public class Node {
private String element;
private List<Node> neighbours;
private boolean isVisited;
public Node(String element, List<Node> neighbours) {
this.element = element;
this.neighbours = neighbours;
}
public void setVisited(boolean visited) {
isVisited = visited;
}
public boolean isVisited() {
return isVisited;
}
public void addNeighbours(Node neighbour) {
neighbours.add(neighbour);
}
public String getElement() {
return element;
}
public List<Node> getNeighbours() {
return neighbours;
}
}
В вашем методе есть путь, по которому он ничего не вернет. А именно в
else-случае. Поймите, что значит попасть в делоelse, а затем спросите себя, какоеNodeвы хотите вернуть в этом случае. Затем верните его, и Java будет счастлива.