Рекурсия - это «разделяй и властвуй» или «повторное использование кода»

11

Рекурсия - как мы все знаем - это одна из тех проблем, когда мыслят вокруг, как будто достигают «вехи» в вашем плавании.

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

Итак, мой вопрос заключается в следующем ...

  • Каковы "шаблоны проблемы", которые требуют решения рекурсии
  • является ли рекурсия формой стратегии «разделяй и властвуй» или формой «повторного использования кода», или же сама является шаблоном проектирования
  • Можете ли вы привести пример реальной проблемы, когда рекурсия приходит на ум как немедленное решение?

-- ОБНОВИТЬ --

многие ответы ссылаются на «реальные проблемы» как обход дерева, факториал и т. д. Я бы предпочел «РЕАЛЬНЫЕ реальные проблемы» - позвольте мне привести вам пример ...

У нас был БОЛЬШОЙ кусок текста (около 30 МБ текста в виде связанного списка structs), и нам нужно было создать его индекс для полнотекстового поиска. Нам нужно было сохранить весь индекс в памяти и переиндексировать текст каждые 10 минут.

Каждые 10 минут мы сравнивали весь текст (два связанных списка, строка за строкой) с вновь созданным фрагментом текста, чтобы увидеть, какая строка была изменена, и затем мы переиндексируем только эту строку - таким образом. мы могли бы избежать необходимости переиндексировать ВЕСЬ текст. Помните - нам нужно было найти точки различия между двумя связанными списками по 30 МБ.

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

Дело в том, как он мог понять, что эту проблему можно решить с помощью интенсивного использования рекурсии?

treecoder
источник
Действительно ли 30 МБ действительно велики в наши дни, когда большинство компьютеров имеют ГБ ОЗУ и ТБ на жестком диске?
JB King
30 МБ НЕ МОГУТ быть большими - но учитывая вид структуры данных, в которую был помещен наш текст, - это был действительно БОЛЬШОЙ кусок текста в PROCESS - и DIFF.
Treecoder
3
Разве «обход структуры папок» не является действительно РЕАЛЬНЫМ? И я совершенно не вижу в вашем примере, как рекурсия должна быть не интуитивной и почему ее использование должно быть особенно заметным. Ваш коллега разработал рекурсивный алгоритм, как и любой другой алгоритм. Вы также можете спросить, как у Хоара возникла идея рекурсивного решения проблемы сортировки.
Конрад Рудольф
2
Правильно ли я считаю, что вы имели в виду «повторное использование кода» скорее как «выполнение одной и той же серии операций неопределенное количество раз»? Это в отличие от «повторного использования кода» в смысле написания универсального кода для использования в другом месте.
Энди Хант
4
Но обход дерева - это «НАСТОЯЩАЯ реальная проблема», с которой многие люди сталкиваются почти ежедневно.
Сокол

Ответы:

16
  • Каковы "шаблоны проблемы", которые требуют решения рекурсии

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

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

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

  • является ли рекурсия формой стратегии «разделяй и властвуй» или формой «повторного использования кода», или же сама является шаблоном проектирования

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

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

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

сокол
источник
7
«Каждая функция, которая может быть реализована с помощью рекурсии, также может быть реализована итеративно, часто путем нажатия и выталкивания стека». В конце концов, в языках, которые используют основанную на стеке память, вы уже помещаете и извлекаете данные функции в стек и из стека при использовании рекурсии.
JAB
Только если вы компилируете или интерпретируете язык на машине ;-) Кроме того, с очень высокой точки зрения, выражение и язык полностью независимы от машины, оборудования и ОС, поэтому стек не обязательно.
Сокол
Ах да, вы абсолютно правы. Я должен был сказать «в реализациях языков / языковых компиляторов, которые используют стековую память».
JAB
Вообще говоря, ты тоже прав. Я не хотел казаться придирчивым.
Сокол
2
Бесконечные списки могут быть выражены без рекурсии, по крайней мере, без рекурсивной реализации. Это могут сделать генераторы Python, как и генераторы в Icon, у которых Python, похоже, заимствовал эту идею. Я верю, что F # может сделать этот трюк, хотя я не уверен. По сути, генераторы - это особый случай совместных процедур (таких как совместная многозадачность), которые хорошо подходят для реализации отложенных списков. Каждый раз, когда генератор «выдает» результат, вызывающая сторона восстанавливает управление, и генератор остается бездействующим, пока не будет запрошен следующий результат.
Steve314
8

является ли рекурсия формой стратегии «разделяй и властвуй» или формой «повторного использования кода», или же сама является шаблоном проектирования

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

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

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

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

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

Конрад Рудольф
источник
Динамическое программирование не всегда естественно выражается как рекурсия. Фактически, динамическое программирование строго относится к табличным подходам - ​​исключая запоминание. Мнения, кажется, расходятся по этому поводу, но «программирование» в «динамическом программировании» на самом деле является математическим термином, относящимся к табличным подходам (часть мелочей, которую я взял из курса алгоритмов с открытым исходным кодом MIT). Строго говоря, динамическое программирование использует оптимальную подструктуру, используя то, что часто проще всего выражать в виде простого цикла. Мемоизация гораздо чаще подразумевает рекурсию, но не обязательно.
Steve314
1
@ Steve314 Я согласен, что практическая реализация DP (будь то в компьютерной программе или вручную) редко использует рекурсию. Но идея по своей сути основана на рекуррентном отношении, которое является просто рекурсивной формулой! - и базовый случай.
Конрад Рудольф
Я согласен, что «оптимальная субструктура» (оптимальное решение имеет оптимальные частичные решения) является рекурсивной идеей. Это математическое / компьютерное представление о рекурсии, не имеющее прямого отношения к реализации, но роль рекурсии в компьютерных науках является важным моментом. Немногие алгоритмы (и, вероятно, не шаблоны проектирования) являются важными инструментами в компьютерной науке - большинство из них являются предметами изучения, а не инструментами, которые можно использовать при изучении чего-либо еще.
Steve314
4
what are the "problem patterns" that call for the solution of recursion

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

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

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

Безопасный
источник
1
+1 за «проблему можно разбить на подзадачи, которые имеют ту же структуру, что и основная проблема»
древовидный кодер
+1 и перефразировать: где решение проблемы относится к дочерним слоям. Мой реальный пример - нахождение платежей по кредитным картам, которые способствуют «партии». Бухгалтерское программное обеспечение будет иметь индивидуальные расходы и пакетный депозит на текущий счет. Мой случай может стать вопросом здесь, так как stackoverflow не был слишком острым по этому поводу. stackoverflow.com/questions/14719806
Крис К,
3

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

Каковы "шаблоны проблемы", которые требуют решения рекурсии

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

является ли рекурсия формой стратегии «разделяй и властвуй» или формой «повторного использования кода», или же сама является шаблоном проектирования

Никто. Разделяй и властвуй использует рекурсию, но может быть реализовано с помощью стеков. Повторное использование кода относится к чему-то еще. Шаблоны проектирования сложнее, чем простая рекурсия.

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

Разбор и все, что имеет дело с древовидными структурами. Даже неявные древовидные структуры.

Михай Марусак
источник
3

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

Следует иметь в виду, что некоторые проблемы могут быть плохо решены с помощью рекурсии, как факториал.

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

JB King
источник
2

Каковы "шаблоны проблемы", которые требуют решения рекурсии

В общих чертах рекурсия требуется, когда вы решаете задачу, где f (x) = f (g (x)) . Если вы не в порядке с бесконечной рекурсией, g (x) не должно оцениваться как x .

является ли рекурсия формой стратегии «разделяй и властвуй» или формой «повторного использования кода», или же сама является шаблоном проектирования

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

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

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

Blrfl
источник
-1

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

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

Например рассмотрим Factorialалгоритм

  • Определите базу: Факториал (1) = 1;
  • Определить факториал n: факториал (n) = n * факториал (n-1);

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

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

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

Ahmad
источник