2014-09-19 4 views
2

Я использую рекурсивный метод для поиска узла в двоичном дереве с помощью ключа. Поэтому, когда я нахожу узел, я устанавливаю его в свою ссылочную переменную (foundNode) и возвращаю. Но проблема в том, что когда я читаю объект, его значение по-прежнему равно нулю. может кто-нибудь помочь.Невозможно установить ссылочную переменную в рекурсивном вызове

findGivenNode(root, key, foundNode, parentStack); 

private boolean findGivenNode(Node node, int key, Node foundNode, Stack<Node> parentStack) { 
    if (node == null) { 
     return false; 
    } 

    parentStack.add(node); 
    if (node.getData() == key) { 
     foundNode = node; 
     return true; 
    } 
    boolean leftReturn = findGivenNode(node.getLeftChild(), key, foundNode, parentStack); 
    boolean RightReturn = findGivenNode(node.getRightChild(), key, foundNode, parentStack);   
    if (leftReturn || RightReturn) { 
     return true; 
    } else { 
     parentStack.pop(); 
     return false; 
    } 
} 

ответ

2

Java не передает аргументы по ссылке, они передаются по значению. Read more here

Проясним на примере. Сделайте ключ, который вы ищете, целым числом со значением 21. Ситуация в начале функции заключается в следующем:

initial_state

Так что теперь, когда вы говорите:

foundNode = node; // this doesn't reflect outside of the method 

Вы меняете значение foundNode локально внутри метода findGivenNode(), его не применяется к вне этого метода. В основном локальная переменная, называемая foundNode, ссылается на узел, который вы хотите изменить, и затем вы делаете эту локальную переменную foundNode ссылкой на новый узел в соответствии с приведенным выше утверждением. Это изменение отражается только внутри функции. Как только ваша функция будет закончена, локальные переменные больше не существуют, так что и эта локальная версия foundNode. Визуальный результат:

wrong_move

Простое решение заключается в использовании Wrapper function

Чтобы отслеживать ссылки, вы можете сделать простой класс-оболочку, которая будет хранить ссылку вы хотите:

private class NodeWrapper { 
    Node foundNode; 
    NodeWrapper() { 
     foundNode = null; 
    } 
} 

Затем вы можете создать новый NodeWrapper и передать его в вашу функцию вместо foundNode

NodeWrapper wrapper = new NodeWrapper(); 
findGivenNode(root, wrapper, key, parentStack); 

Тогда внутри вашей функции вместо:

foundNode = node; 

Вы говорите:

wrapper.foundNode = node; 

Таким образом, вы можете сохранить ссылку на протяжении рекурсии внутри NodeWrapper. Значение:

NodeWrapper wrapper = new NodeWrapper(); 
findGivenNode(root, wrapper, key, parentStack); 
// at this point, wrapper.foundNode will hold the reference to the node you need 
// or null if the node wasn't found 

На другой ноте выше метода вы имеете этот прототип функции:

findGivenNode(root, key, foundNode, parentStack); 

Похоже, что кто-то до сих пор используется для C/C++ :)

Это ненужное в Java , вы можете прочитать this question thread за то, что это или просто Google.

+0

спасибо за разъяснение, но, установив (foundNode = node), я пытаюсь получить ссылку на узел, у которого есть ключ, а не сам узел.Во-вторых, foundNode - это только ссылочная переменная, поэтому нельзя установить значение, вызвав любой из методов setter. –

+0

Во второй части, да, это возможно. 'foundNode' указывает на узел, который вы хотите изменить, чтобы он имел доступ к методам этого узла. – nem035

+0

Но изменение узла не является целью установки ссылочной переменной на этот узел. Все, что мне нужно, это ссылка на этот узел. который я не получаю, если я не делаю что-то вроде 'foundNode = node; return foundNode; 'И изменить тип возвращаемого метода из' void' в 'Node'. –