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

Что такое 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 ответов

Запишите функцию, которая переводит число как 12 345,67 к "двенадцати тысячам тремстам сорока пяти долларам и шестидесяти семи центам".

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

Я записал синтаксический анализатор XML, как только это будет намного более трудно записать без рекурсии.

я предполагаю, что можно всегда использовать стек + повторение, но иногда рекурсия настолько изящна.

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

Нахождение медианы в среднем случае O (n). Эквивалентный нахождению k-th самого большого объекта в списке n вещей, с k=n/2:

интервал kthLargest (список, k, во-первых, в последний раз) {j = раздел (список, во-первых, в последний раз), если (k == j) еще возвращают список [j] если (k

Здесь, partition выборы элемент центра, и в одной передаче через данные, перестраивает список так, чтобы объекты меньше, чем центр были на первом месте, тогда центр, затем объекты, больше, чем центр. "kthLargest" алгоритм очень похож на quicksort, но рекурсивно вызывает только одну сторону списка.

Для меня, это - самый простой рекурсивный алгоритм, который работает быстрее, чем итеративный алгоритм. Это использует 2*n сравнения в среднем, независимо от k. Это намного лучше, чем наивный подход выполнения k проходит через данные, находя минимум каждым разом, и отбрасывая его.

Alejo

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

Все, где Вы используете повторение, сделано более естественное с рекурсией если оно где не для практического ограничения порождения переполнения стека;-)

, Но серьезно Рекурсия и Повторение являются очень взаимозаменяемыми, можно переписать весь алгоритм с помощью рекурсии для использования повторения и наоборот. Математики как рекурсия и программисты как повторение. Это, вероятно, также, почему Вы видите все эти изобретенные примеры, которые Вы упоминаете. Я думаю, что метод математического доказательства под названием Математическая индукция имеет что-то, чтобы сделать почему математики как рекурсия. http://en.wikipedia.org/wiki/Mathematical_induction

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

Я просто записал рекурсивную функцию, чтобы выяснить, должен ли класс был быть сериализирован с помощью DataContractSerializer. Большая проблема шла с шаблонами/дженериками, где класс мог содержать другие типы, которые должны были быть datacontract, сериализированным..., таким образом, это, проходят каждый тип, если это не datacontractserializable проверка, это - типы.

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

Главным образом рекурсия является очень естественной для контакта с рекурсивными структурами данных. Это в основном означает структуры списка и древовидные структуры. Но рекурсия является также хорошим естественным способом/creating/древовидных структур на лету в некотором роде делить-и-побеждать, например quicksort или двоичный поиск.

я думаю, что Ваш вопрос немного дезинформирован в одном смысле. Что не реально о поиске в глубину? Существует много, можно сделать с поиском в глубину.

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

1
ответ дан 2 revs, 2 users 77%Tim Lovell-Smith 24 November 2019 в 08:07
поделиться

Я записал дерево в C# для обработки поисков на таблице, что 6 сегментированный ключ со случаями по умолчанию (если ключ [0] не существует, используйте случай по умолчанию и продолжите). Поиски были сделаны рекурсивно. Я попробовал словарь словарей словарей (и т.д.), и это стало слишком сложным очень быстро.

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

я не видел многих примеров того, что люди сделали, а скорее библиотеки, которыми они пользовались. Надо надеяться, это дает Вам что-то для размышления о.

0
ответ дан Austin Salonen 24 November 2019 в 08:07
поделиться

Геометрические вычисления для GIS или картографии, такие как нахождение края круга.

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

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

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

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

, Например:

Комнаты 1, 2, 3 могут сыпаться друг другу. Эта комната для детей, которые не могут идти самостоятельно, таким образом, Вы хотите, чтобы они далеко от всего остального избежали отвлечения и другой болезни (который не является вещью пожилым людям, но к 6 мес это может стать очень плохим. Если все три полны, человеку нужно отказать во входе.

Комнаты 4, 5, 6 могут сыпаться друг другу. Эта комната для людей, у которых аллергия на арахис и таким образом, они не могут войти в другие комнаты (который может иметь материал с арахисом). Если все три становятся полными, предлагают предупреждение, спрашивая их уровень аллергии и perahsp, они могут быть предоставленным доступом.

В любой момент времени, комнаты могут измениться. Таким образом, можно позволить комнате 7-14 быть комнатами без арахисов. Вы не знаете сколько комнат проверять.

Или, возможно, Вы хотите отделиться на основе возраста. Класс, пол, и т.д. Это просто пара примеров, к которым я вошел.

0
ответ дан Kenny Mann 24 November 2019 в 08:07
поделиться

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

public MenuElement(BHSSiteMap node, string role)
    {
        if (CheckRole(node, role))
        {
            ParentNode = node;

            // get site map collection order by sequence
            BHSSiteMapCollection children = new BHSSiteMapCollection();

            Query q = BHSSiteMap.CreateQuery()
                    .WHERE(BHSSiteMap.Columns.Parent, Comparison.Equals, ParentNode.Id)
                    .ORDER_BY(BHSSiteMap.Columns.Sequence, "ASC");

            children.LoadAndCloseReader(q.ExecuteReader());

            if (children.Count > 0)
            {
                ChildNodes = new List<MenuElement>();

                foreach (BHSSiteMap child in children)
                {
                    MenuElement childME = new MenuElement(child, role);
                    ChildNodes.Add(childME);
                }
            }
        }
    }
0
ответ дан JPrescottSanders 24 November 2019 в 08:07
поделиться

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

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

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

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

я использовал Цепочку шаблона Ответственности, таким образом, Объект-обработчик или обрабатывает сам запрос или делегирует его вниз цепочка. Полезно зарегистрировать конструкцию цепочки:

public String getChainString() {
    cs = this.getClass().toString();
    if(this.delegate != null) {
        cs += "->" + delegate.getChainString();
    }
    return cs;
}

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

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

Мы используем их, чтобы сделать новаторский SQL.

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

0
ответ дан 2 revs, 2 users 80%www.smackfu.com 24 November 2019 в 08:07
поделиться

"Реальной" проблемой, решенной рекурсией, были бы матрешки. Вашей функцией является OpenDoll ().

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

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

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

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

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

Ханойские башни

Вот являются той, с которой можно взаимодействовать: http://www.mazeworks.com/hanoi/

Используя рекуррентные соотношения, точное количество перемещений, которых требует это решение, может быть вычислено: в€2 ч’ 1. Этот результат получен путем отмечания, что шаги 1 и 3 берут Th в€’ 1 перемещение, и шаг 2 берет одно перемещение, давая Th = 2Th в€’ 1 + 1. См.: http://en.wikipedia.org/wiki/Towers_of_hanoi#Recursive_solution

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

Проверьте, собирается ли созданное изображение работать в ограниченном поле размера.

function check_size($font_size, $font, $text, $width, $height) {
        if (!is_string($text)) {
            throw new Exception('Invalid type for $text');
        }   
        $box = imagettfbbox($font_size, 0, $font, $text);
        $box['width'] = abs($box[2] - $box[0]);
        if ($box[0] < -1) {
            $box['width'] = abs($box[2]) + abs($box[0]) - 1;
        }   
        $box['height'] = abs($box[7]) - abs($box[1]);
        if ($box[3] > 0) {
            $box['height'] = abs($box[7] - abs($box[1])) - 1;
        }   
        return ($box['height'] < $height && $box['width'] < $width) ? array($font_size, $box['width'], $height) : $this->check_size($font_size - 1, $font, $text, $width, $height);
    }
0
ответ дан mk. 24 November 2019 в 08:07
поделиться

Пример реального мира косвенной рекурсии спросил бы Ваших родителей, если у Вас может быть та видеоигра для рождества. Папа: "Спросите мама".... Мама: "Спросите папа". [Короче говоря, "Нет, но мы не хотим говорить Вам это, чтобы Вы не бросаете истерику".]

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

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

Ссылка: Пример кода рекурсии и мемоизации

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

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