заявление о возврате Java - PullRequest
       22

заявление о возврате Java

3 голосов
/ 11 января 2010

У меня вопрос по поводу следующего кода

private void printTree(Node node){
    if(node==null) return;
    printTree(node.left);
    System.out.print(node.data+" ");
    printTree(node.right);
}

На самом деле я не получаю точку «возврата»; Заявление там. Похоже, если узел равен нулю, код ничего не возвращает. но затем без этой строки компилятор генерирует ошибку исключения.

Ответы [ 8 ]

16 голосов
/ 11 января 2010

Это рекурсивная функция (которая вызывает себя несколько раз). Цель return состоит в том, чтобы гарантировать, что он не будет пытаться делать это вечно, что приведет к исключению нулевого указателя при запуске из нижней части дерева.

То, что произойдет, это то, что когда вы в первый раз вызываете эту функцию с узлом (обычно, но не всегда, с корневым узлом), она сначала распечатает левое поддерево этого узла, затем значение узла сам, то правое поддерево этого узла.

Способ, которым он печатает поддеревья, заключается в вызове самого себя с помощью узла верхнего уровня этого поддерева. Это очень распространенный метод элегантной обработки рекурсивных структур.

Тест для null таков, что он имеет условие, при котором поиск вниз по уровням дерева останавливается, когда он достигает узла, у которого нет дочерних элементов на конкретной стороне, которую вы исследуете (слева или справа).

В качестве примера предположим, что у вас есть следующее дерево (заглавные буквы с их номерами являются действительными узлами, а числа являются их значением, а маркеры === равны нулю):

             A26                Level 0
              |
       +------+------+
       |             |
      B14           C84         Level 1
       |             |
    +--+--+       +--+--+
    |     |       |     |
   D11   ===     ===   E99      Level 2
    |                   |
 +--+--+             +--+--+
 |     |             |     |
===   ===           ===   ===   Level 3

Вот что произойдет, когда вы вызовете функцию с помощью A.

You call the function (level 0) with A.
  The function will call itself (level 1) with B (A left).
    The function will call itself (level 2) with D (B left).
      The function will call itself (level 3) with null (D left).
        The function will return to level 2.
      The function will print out 11 from D.
      The function will call itself (level 3) with null (D right).
        The function will return to level 2.
      The function will return to level 1.
    The function will print out 14 from B.
    The function will call itself (level 2) with null (B right).
      The function will return to level 1.
    The function will return to level 0.
  The function will print out 26 from A.
  The function will call itself (level 1) with C (A right).
    The function will call itself (level 2) with null (C left).
      The function will return to level 1.
    The function will print out 84 from C.
    The function will call itself (level 2) with E (C right).
      The function will call itself (level 3) with null (E left).
        The function will return to level 2.
      The function will print out 99 from E.
      The function will call itself (level 3) with null (E right).
        The function will return to level 2.
      The function will return to level 1.
    The function will return to level 0.
  The function will return to you.

В результате получается распечатка последовательности DBACE, которая в отсортированном дереве представляет элементы в отсортированном порядке (11, 14, 26, 84, 99).


Или более простая версия, если вы не можете прочитать мое объемное объяснение выше:

             A26                Level 0
              |
       +------+------+
       |             |
      B14           ===         Level 1
       |
    +--+--+
    |     |
   ===   ===                    Level 2

You call the function (level 0) with A.
  The function will call itself (level 1) with B (A left).
    The function will call itself (level 2) with null (B left).
      The function will return to level 1.
    The function will print out 14 from B.
    The function will call itself (level 2) with null (B right).
      The function will return to level 1.
    The function will return to level 0.
  The function will print out 26 from A.
  The function will call itself (level 1) with null (A right).
    The function will return to level 0.
  The function will return to you.

В этом случае вы получите BA или (14,26).

4 голосов
/ 11 января 2010

Любой объявленный метод void не возвращает значение. Он не должен содержать оператор возврата, но он может это сделать. В таком случае оператор return может использоваться для перехода из блока потока управления и выхода из метода и используется просто так:

return;

Из Java LangSpec:

14,17 Заявление о возврате

Оператор возврата возвращает управление вызывающий метод (§8.4, §15.12) или конструктор (§8.8, §15.9).

ReturnStatement:
        return Expressionopt ;

оператор возврата без выражения должны содержаться в теле метод, который объявлен, используя ключевое слово void, не возвращать никакого значения (§8.4), или в теле конструктор (§8.8). Время компиляции ошибка возникает при возврате оператора появляется в инициализаторе экземпляра или статический инициализатор (§8.7). оператор возврата без выражения пытается передать управление вызывающий метод или конструктор это содержит это. Чтобы быть точным, оператор возврата без выражения всегда завершается внезапно, причина возвращение без значения.

Оператор возврата с выражением должен содержаться в методе декларация, которая объявлена ​​для возврата значение (§8.4) или ошибка времени компиляции происходит. Выражение должно обозначать переменная или значение некоторого типа T, или происходит ошибка времени компиляции. Тип Т должен быть назначен (§5.2) объявленный тип результата метода, или происходит ошибка времени компиляции.

0 голосов
/ 01 июня 2012

Оператор возврата прост для понимания следующим образом:

Методы, которые не имеют возвращаемого типа, не могут возвращать значение, но возвращают элемент управления.

Любой метод, который может вернуть значение, может вернуть значение, которое должно быть совместимым с возвращаемым типом метода.

0 голосов
/ 11 января 2010

Иногда трудно распознать возвращение, которого нет в конце. Большинство людей привыкли находить это здесь. Кроме того, возврат, который ничего не возвращает, также может сбить с толку. Более очевидный способ написать это будет:

private void printTree(Node node) {
    if(node!=null) {
        printTree(node.left);
        System.out.print(node.data+" ");
        printTree(node.right);
    }
}

Итак, просто "если есть узел, посетите его"!

0 голосов
/ 11 января 2010

Менее запутанный способ написать это будет:

private void printTree(Node node){
    if (node.left != null) {
       printTree(node.left);
    }
    System.out.print(node.data);
    if (node.right != null) {
       System.out.print(" ");
       printTree(node.right);
    }
}
0 голосов
/ 11 января 2010

оператор return здесь выступает в качестве завершающего условия для рекурсивного вызова. Каждый рекурсивный метод требует обязательного условия завершения, иначе он идет по бесконечному циклу.

if(node==null) return;

этот оператор в основном означает, что вы достигли конечного узла (последнего узла ветви) и прекращает любое дальнейшее перемещение курсора.

Исключение, которое вы получаете при удалении возврата, связано с тем, что у вас больше нет узлов для перемещения после достижения конечного узла, а операторы printTree(node.left); & printTree(node.right); недопустимы.

0 голосов
/ 11 января 2010

У вас также есть возврат, чтобы вы не вызывали node.data. Помните, что если оно пустое, вы не можете вызывать метод экземпляра для него.

0 голосов
/ 11 января 2010

Мне кажется, что если ваш узел имеет значение null, он выйдет из вызова функции до того, как сгенерирует исключение NullReferenceException. Поскольку он рекурсивный, ему нужно иметь дело с узлами (листьями) дерева путем «возврата» к его родительским узлам.

...