Реальные примеры рекурсии

Что такое проблемы реального мира, где рекурсивный подход является естественным решением, помимо поиска по глубине (DFS)?

(Я не считаю Башня Ханоя, Число Фибоначчи или факториальные проблемы реального мира. Они немного умудряются в моем уме.)

Ответ 1

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

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

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

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

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

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

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

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

Ответ 2

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

A sunflower

Ответ 3

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

Вот реализация 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());
            }
        }       
    }

}

Ответ 4

Quicksort, merge sort, и большинство других видов N-log N.

Ответ 6

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

Ответ 7

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

Ответ 8

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

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

Ответ 9

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

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);
    }
}

Ответ 10

Знаменитый цикл Eval/Apply из SICP

alt text

Вот определение eval:

(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))))

Вот определение apply:

(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))))

Вот определение eval-последовательности:

(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))))

evalapplyeval-sequenceeval

Ответ 11

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

Ответ 12

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

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

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

Ответ 13

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

Ответ 14

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

Ответ 15

Требование реального мира, которое я получил недавно:

Требование A: выполнить эту функцию после тщательного понимания требования A.

Ответ 16

Некоторые отличные примеры рекурсии находятся в функциональном программировании. В функциональных языках программирования (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" (позволяя нам разбить рекурсию), else вернем значение головы + значение суммы, вызванное с остальными элементами (следовательно, наша рекурсия).

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

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

Ответ 17

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

Ответ 18

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

Хорошие примеры того, где вещи, которые содержат более мелкие части, похожие на себя:

  • древовидная структура (ветка подобна дереву)
  • списки (часть списка по-прежнему является списком)
  • контейнеры (русские куклы)
  • (часть последовательности выглядит следующим образом)
  • группы объектов (подгруппа - это все еще группа объектов)

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

Ниже приводятся некоторые рекурсивные алгоритмы сортировки, алгоритмы древовидной ходьбы, алгоритмы карты/уменьшения, деление и победа.

В компьютерном программировании большинство языков типа call-return на основе стека уже имеют встроенные возможности для рекурсии: т.е.

  • разбить проблему на более мелкие части == > называть себя меньшим подмножеством исходных данных),
  • отслеживать, как разделяются фрагменты == > стек вызовов,
  • сшить результаты назад == > возврат на основе стека

Ответ 19

Обратная связь в иерархической организации.

Топ-босс говорит топ-менеджерам, чтобы собрать отзывы от всех в компании.

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

И на линии.

Люди без прямых отчетов - листовые узлы в дереве - дают свои отзывы.

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

В конце концов вся обратная связь заставляет его вернуться к верхнему боссу.

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

Ответ 20

  • Разбор XML.
  • Эффективный поиск в многомерных пространствах. E. g. четырехъярусные деревья в 2D, oct-деревья в 3D, kd-деревья и т.д.
  • Иерархическая кластеризация.
  • Подумайте об этом, переходя к любой иерархической структуре, естественно, поддается рекурсии.
  • Метапрограммирование шаблонов в С++, где нет циклов, и рекурсия - единственный способ.

Ответ 21

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

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

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

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

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

Во всяком случае, мой $.02

Ответ 22

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

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

Ответ 23

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

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

Ответ 24

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

Ответ 26

Анализ дерева элементов управления в Windows Forms или WebForms (.NET Windows Forms/ASP.NET).

Ответ 27

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

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

Ответ 28

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

Ответ 29

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

Я думаю, что ваш вопрос немного ошибочен в одном смысле. Что не реально в глубине первого поиска? Там вы можете много сделать с поиском глубины.

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

Ответ 30

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