[Закрываются] реальные примеры рекурсии

Что такое NullPointerException?

Хорошим местом для начала является JavaDocs . Они охватывают это:

Брошено, когда приложение пытается использовать null в случае, когда требуется объект. К ним относятся:

  • Вызов метода экземпляра нулевого объекта.
  • Доступ или изменение поля нулевого объекта.
  • Выполнение длины null, как если бы это был массив.
  • Доступ или изменение слотов с нулевым значением, как если бы это был массив.
  • Бросать нуль, как если бы это было значение Throwable.

Приложения должны бросать экземпляры этого класса для указания других незаконных видов использования нулевого объекта.

blockquote>

Также, если вы попытаетесь использовать нулевую ссылку с synchronized, который также выдаст это исключение, за JLS :

SynchronizedStatement:
    synchronized ( Expression ) Block
  • В противном случае, если значение выражения равно null, NullPointerException.
blockquote>

Как это исправить?

Итак, у вас есть NullPointerException. Как вы это исправите? Возьмем простой пример, который выдает NullPointerException:

public class Printer {
    private String name;

    public void setName(String name) {
        this.name = name;
    }

    public void print() {
        printString(name);
    }

    private void printString(String s) {
        System.out.println(s + " (" + s.length() + ")");
    }

    public static void main(String[] args) {
        Printer printer = new Printer();
        printer.print();
    }
}

Идентифицирует нулевые значения

. Первый шаг - точно определить , значения которого вызывают исключение . Для этого нам нужно выполнить некоторую отладку. Важно научиться читать stacktrace . Это покажет вам, где было выбрано исключение:

Exception in thread "main" java.lang.NullPointerException
    at Printer.printString(Printer.java:13)
    at Printer.print(Printer.java:9)
    at Printer.main(Printer.java:19)

Здесь мы видим, что исключение выбрано в строке 13 (в методе printString). Посмотрите на строку и проверьте, какие значения равны нулю, добавив протоколирующие операторы или используя отладчик . Мы обнаруживаем, что s имеет значение null, а вызов метода length на него вызывает исключение. Мы видим, что программа прекращает бросать исключение, когда s.length() удаляется из метода.

Трассировка, где эти значения взяты из

Затем проверьте, откуда это значение. Следуя вызовам метода, мы видим, что s передается с printString(name) в методе print(), а this.name - null.

Трассировка, где эти значения должны быть установлены

Где установлен this.name? В методе setName(String). С некоторой дополнительной отладкой мы видим, что этот метод вообще не вызывается. Если этот метод был вызван, обязательно проверьте порядок , что эти методы вызывают, а метод set не будет называться после методом печати. ​​

Этого достаточно, чтобы дать нам решение: добавить вызов printer.setName() перед вызовом printer.print().

Другие исправления

Переменная может иметь значение по умолчанию setName может помешать ему установить значение null):

private String name = "";

Либо метод print, либо printString может проверить значение null например:

printString((name == null) ? "" : name);

Или вы можете создать класс, чтобы name всегда имел ненулевое значение :

public class Printer {
    private final String name;

    public Printer(String name) {
        this.name = Objects.requireNonNull(name);
    }

    public void print() {
        printString(name);
    }

    private void printString(String s) {
        System.out.println(s + " (" + s.length() + ")");
    }

    public static void main(String[] args) {
        Printer printer = new Printer("123");
        printer.print();
    }
}

См. также:

Я все еще не могу найти проблему

Если вы попытались отладить проблему и до сих пор не имеете решения, вы можете отправить вопрос для получения дополнительной справки, но не забудьте включить то, что вы пробовали до сих пор. Как минимум, включите stacktrace в вопрос и отметьте важные номера строк в коде. Также попробуйте сначала упростить код (см. SSCCE ).

85
задан 7 revs, 6 users 50% 11 May 2014 в 15:44
поделиться

50 ответов

Существует много mathy примеров здесь, но Вы хотели реальный мир пример, таким образом, с небольшим количеством взглядов, это является возможно лучшим, я могу предложить:

Вы находите человека, который сократил данное заразное заражение, которое не является фатальным, и фиксирует себя быстро (Тип A), За исключением каждого 5-го человека (Мы назовем их типом B), кто становится постоянно зараженным им, и не появляется симптомов и просто действует распорка.

Это создает довольно раздражающие волны опустошения, когда когда-либо тип B заражает множество типа A.

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

путем, Вы сделали бы это, будет социальное открытие, учитывая зараженного человека (Тип A), выберет все их контакты на прошлой неделе, отмечая каждый контакт на "куче". То, когда Вы тестируете человека, заражено, добавьте их к "развить" очереди. Когда человек является типом B, добавьте их к "развитию" в голове (потому что Вы хотите остановить это быстро).

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

Повторение, пока очередь зараженных людей не становится 0, и затем ожидает другой вспышки..

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

32
ответ дан 2 revs, 2 users 97% 24 November 2019 в 08:07
поделиться

Умножение натуральных чисел является реальным примером рекурсии:

To multiply x by y
  if x is 0
    the answer is 0
  if x is 1
    the answer is y
  otherwise
    multiply x - 1 by y, and add x
1
ответ дан Apocalisp 24 November 2019 в 08:07
поделиться

Так же комментарий о компиляторах. Узлы абстрактного синтаксического дерева естественно предоставляют себя рекурсии. Все рекурсивные структуры данных (связанные списки, деревья, графики, и т.д.) также более легко обрабатываются с рекурсией. Я думаю, что большинство из нас не добирается для использования рекурсии много, как только мы вне школы из-за типов реальных проблем, но хорошо знать о нем как об опции.

1
ответ дан origin 24 November 2019 в 08:07
поделиться

Телефон и кабельные компании поддерживают модель их топологии проводного соединения, которая в действительности является большой сетью или графиком. Рекурсия является одним способом пересечь эту модель, когда Вы хотите найти всего родителя или все дочерние элементы.

, Так как рекурсия является дорогой от обработки и перспективы памяти, этот шаг обычно только выполняется, когда топология изменяется, и результат хранится в измененном предварительно заказанном формате списка.

1
ответ дан Steve Moyer 24 November 2019 в 08:07
поделиться

Индуктивное рассуждение, процесс формирования понятия, является рекурсивным по своей природе. Ваш мозг делает все это время в реальном мире.

1
ответ дан Apocalisp 24 November 2019 в 08:07
поделиться

Как насчет чего-либо вовлекающего структуру каталогов в файловую систему. Рекурсивно находя файлы, удаляя файлы, создавая каталоги, и т.д.

Вот реализация Java, которая рекурсивно распечатывает содержание каталога и его подкаталогов.

import java.io.File;

public class DirectoryContentAnalyserOne implements DirectoryContentAnalyser {

    private static StringBuilder indentation = new StringBuilder();

    public static void main (String args [] ){
        // Here you pass the path to the directory to be scanned
        getDirectoryContent("C:\\DirOne\\DirTwo\\AndSoOn");
    }

    private static void getDirectoryContent(String filePath) {

        File currentDirOrFile = new File(filePath);

        if ( !currentDirOrFile.exists() ){
            return;
        }
        else if ( currentDirOrFile.isFile() ){
            System.out.println(indentation + currentDirOrFile.getName());
            return;
        }
        else{
            System.out.println("\n" + indentation + "|_" +currentDirOrFile.getName());
            indentation.append("   ");

            for ( String currentFileOrDirName : currentDirOrFile.list()){
                getPrivateDirectoryContent(currentDirOrFile + "\\" + currentFileOrDirName);
            }

            if (indentation.length() - 3 > 3 ){
                indentation.delete(indentation.length() - 3, indentation.length());
            }
        }       
    }

}
64
ответ дан 3 revs, 3 users 91% 24 November 2019 в 08:07
поделиться

Пример реального мира рекурсии

A sunflower

105
ответ дан 2 revs 24 November 2019 в 08:07
поделиться

Quicksort, сортировка слиянием , и большая часть другого N-журнала N виды.

45
ответ дан 2 revs, 2 users 71% 24 November 2019 в 08:07
поделиться

Пример матового Дилларда хорош. В более общем плане любой обход дерева может обычно обрабатываться рекурсией очень легко. Например, компилируя деревья синтаксического анализа, идя по XML или HTML, и т.д.

16
ответ дан Cody Brocious 24 November 2019 в 08:07
поделиться

Рекурсия часто используется в реализациях алгоритм Отслеживания в обратном порядке . Для "реального" приложения этого, как насчет решатель Судоку ?

16
ответ дан 2 revs, 2 users 67% 24 November 2019 в 08:07
поделиться

Рекурсия является соответствующей каждый раз, когда проблема может быть решена путем деления ее в подпроблемы, которые могут использовать тот же алгоритм для решения их. Алгоритмы на деревьях и отсортированные списки являются естественным соответствием. Много проблем в вычислительной геометрии (и 3D игры) могут быть решены рекурсивно с помощью двоичное пространство, делящее (BSP) деревья, толстые подразделения , или другие способы разделить мир на подразделения.

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

13
ответ дан 3 revs, 3 users 67% 24 November 2019 в 08:07
поделиться

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

11
ответ дан Martin Cote 24 November 2019 в 08:07
поделиться

Отключение/установка, только для чтения для всех детей, управляет в контейнерном управлении. Я должен был сделать это, потому что некоторые дочерние средства управления были самими контейнерами.

public static void SetReadOnly(Control ctrl, bool readOnly)
{
    //set the control read only
    SetControlReadOnly(ctrl, readOnly);

    if (ctrl.Controls != null && ctrl.Controls.Count > 0)
    {
        //recursively loop through all child controls
        foreach (Control c in ctrl.Controls)
            SetReadOnly(c, readOnly);
    }
}
9
ответ дан chitza 24 November 2019 в 08:07
поделиться

Известный цикл Оценки/Применять от SICP

alt text
(источник: mit.edu )

Вот определение оценки:

(define (eval exp env)
  (cond ((self-evaluating? exp) exp)
        ((variable? exp) (lookup-variable-value exp env))
        ((quoted? exp) (text-of-quotation exp))
        ((assignment? exp) (eval-assignment exp env))
        ((definition? exp) (eval-definition exp env))
        ((if? exp) (eval-if exp env))
        ((lambda? exp)
         (make-procedure (lambda-parameters exp)
                         (lambda-body exp)
                         env))
        ((begin? exp) 
         (eval-sequence (begin-actions exp) env))
        ((cond? exp) (eval (cond->if exp) env))
        ((application? exp)
         (apply (eval (operator exp) env)
                (list-of-values (operands exp) env)))
        (else
         (error "Unknown expression type - EVAL" exp))))

Вот определение, подайте заявку:

(define (apply procedure arguments)
  (cond ((primitive-procedure? procedure)
         (apply-primitive-procedure procedure arguments))
        ((compound-procedure? procedure)
         (eval-sequence
           (procedure-body procedure)
           (extend-environment
             (procedure-parameters procedure)
             arguments
             (procedure-environment procedure))))
        (else
         (error
          "Unknown procedure type - APPLY" procedure))))

Вот определение последовательности оценки:

(define (eval-sequence exps env)
  (cond ((last-exp? exps) (eval (first-exp exps) env))
        (else (eval (first-exp exps) env)
              (eval-sequence (rest-exps exps) env))))

eval-> apply-> eval-sequence-> eval

8
ответ дан 4 revs, 3 users 97% 24 November 2019 в 08:07
поделиться

Рекурсия используется в вещах как деревья BSP для обнаружения коллизий в разработке игр (и другие подобные области).

7
ответ дан Mark 24 November 2019 в 08:07
поделиться

Синтаксические анализаторы и компиляторы могут быть записаны в методе рекурсивного спуска. Не лучший способ сделать это, поскольку инструменты как lex/yacc генерируют более быстрые и более эффективные синтаксические анализаторы, но концептуально простой и легкий для реализации, таким образом, они остаются распространенными.

4
ответ дан davenpcj 24 November 2019 в 08:07
поделиться

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

Ищущие слова в словаре часто выполняются подобной двоичному поиску техникой, которая является рекурсивной.

В организациях, боссы часто дают команды начальникам отделов, которые в свою очередь дают команды менеджерам и так далее.

7
ответ дан tkerwin 24 November 2019 в 08:07
поделиться

Требование реального мира я недавно добрался:

Требование A: Реализуйте эту опцию после полного понимания Требования A.

4
ответ дан dragon 24 November 2019 в 08:07
поделиться

У меня есть система, которая использует чистый хвостовая рекурсия в нескольких местах для моделирования конечного автомата.

4
ответ дан 2 revs, 2 users 67% 24 November 2019 в 08:07
поделиться

XML или пересечение чего-либо, что является деревом. Хотя, честно говоря, я в значительной степени никогда не использую рекурсию в своем задании.

3
ответ дан Charles Graham 24 November 2019 в 08:07
поделиться

Некоторые яркие примеры рекурсии найдены в функциональное программирование языки. На языках функционального программирования ( Erlang, Haskell, ML / OCaml / F#, и т.д.), очень распространено иметь любую рекурсию использования обработки списков.

При контакте со списками на типичных обязательных языках стиля ООП, очень распространено рассматривать списки, реализованные как связанные списки ([item1-> item2-> item3-> item4]). Однако на некоторых языках функционального программирования, Вы находите, что сами списки реализованы рекурсивно, где "заголовок" списка указывает на первый объект в списке, и "хвост" указывает на список, содержащий остальную часть объектов ([item1-> [item2-> [item3-> [item4-> []]]]]). Это является довольно творческим, по-моему.

Эта обработка списков, когда объединено с сопоставлением с образцом, ОЧЕНЬ мощна. Скажем, я хочу суммировать список чисел:

let rec Sum numbers =
    match numbers with
    | [] -> 0
    | head::tail -> head + Sum tail

Это по существу говорит, "если нас позвонили с пустым списком, возвратитесь 0" (разрешение нам повредить рекурсию), еще возвратите значение головы + значение Суммы, названной с остающимися объектами (следовательно, наша рекурсия).

, Например, у меня мог бы быть список URL , я думаю, разбивают все URL каждый URL-адреса на, и затем я сокращаю общее количество ссылок на все URL для генерации "значений" для страницы (подход, который Google проявляет с PageRank и что можно найти определенным в исходной газете MapReduce ). Можно сделать это для генерации подсчетов слов в документе также. И многие, многие, много других вещей также.

можно расширить этот функциональный шаблон до любого типа [1 110] код MapReduce, где Вы можете, беря список чего-то, преобразовывая его и возвращая что-то еще (управляет ли другой список или некоторая zip в списке).

4
ответ дан 2 revs, 2 users 64% 24 November 2019 в 08:07
поделиться

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

предположим также Ваш {user|client|customer|boss} запрашивает поместить пройденный путь на каждой странице для показа, где Вы находитесь в дереве.

Для любой данной страницы n, Вы будете, может хотеть приблизиться к родителю n и его родителю, и так далее, рекурсивно создать список узлов назад до корня дерева страницы.

, Конечно, Вы поражаете дб несколько раз на страницу в том примере, таким образом, можно хотеть использовать некоторое искажение SQL, где Вы ищете таблицу страниц как a и таблицу страниц снова как b, и присоединяетесь к a.id с b.parent, таким образом, Вы заставляете базу данных сделать рекурсивные соединения. Это было некоторое время, таким образом, мой синтаксис, вероятно, не полезен.

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

Так или иначе, это составляет мои.02$

2
ответ дан Sam McAfee 24 November 2019 в 08:07
поделиться

У Вас есть организационное дерево, которое является уровнями N глубоко. Несколько из узлов проверяются, и Вы хотите расшириться только до тех узлов, которые были проверены.

Это - что-то, что я на самом деле кодировал. Ее хорошее и легкое с рекурсией.

2
ответ дан MagicKat 24 November 2019 в 08:07
поделиться

Вычисления для финансов/физики, такие как составные средние числа.

2
ответ дан Apocalisp 24 November 2019 в 08:07
поделиться

В моем задании у нас есть система с универсальной структурой данных, которая может быть описана как дерево. Это означает, что рекурсия является очень эффективной техникой для работы с данными.

Решение его без рекурсии потребовало бы большого количества ненужного кода. Проблема с рекурсией состоит в том, что не легко следовать за тем, что происходит. Действительно необходимо сконцентрироваться при следовании за потоком выполнения. Но когда это работает, код является изящным и эффективным.

2
ответ дан Tommy 24 November 2019 в 08:07
поделиться

Парсинг дерева средств управления в Windows Forms или WebForms (.NET Windows Forms / ASP.NET ).

2
ответ дан 2 revs, 2 users 71% 24 November 2019 в 08:07
поделиться
  • Парсинг файл XML .
  • Эффективный поиск в многомерных пробелах. Например, деревья квадрантов в 2D, деревья октября в 3D, kd-деревьях, и т.д.
  • Иерархическая кластеризация.
  • Задумываются о нем, пересечение любой иерархической структуры естественно предоставляет себя рекурсии.
  • Шаблонное метапрограммирование в C++, где нет никаких циклов и рекурсии, является единственным путем.
2
ответ дан 2 revs, 2 users 56% 24 November 2019 в 08:07
поделиться

Лучший пример, который я знаю, quicksort, это намного более просто с рекурсией. Смотрите на:

shop.oreilly.com/product/9780596510046.do

www.amazon.com/Beautiful-Code-Leading-Programmers-Practice/dp/0596510047

(Нажимают на первый подзаголовок в соответствии с главой 3: "Самый красивый код я когда-либо писал").

2
ответ дан 3 revs, 2 users 82% 24 November 2019 в 08:07
поделиться

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

1
ответ дан Apocalisp 24 November 2019 в 08:07
поделиться

Что-либо программа с деревом или структурами данных графика будет, вероятно, иметь некоторую рекурсию.

1
ответ дан Mark Harrison 24 November 2019 в 08:07
поделиться
Другие вопросы по тегам:

Похожие вопросы: