Рекурсія - це "розділити і перемогти" або "повторне використання коду"


11

Рекурсія - як ми всі знаємо - одна з тих проблем - те, що обернути голову, відчуває, як досягти "рубіж" у вашому плановому плаванні.

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

Тож моє запитання таке ...

  • які "схеми проблем" вимагають вирішення рекурсії
  • це рекурсія, форма стратегії "ділити і перемагай" або форма "повторного використання коду" - або, сама по собі, модель дизайну.
  • чи можете ви навести приклад реальної світової проблеми, коли рекурсія приходить в голову як негайне рішення

- ОНОВЛЕННЯ -

багато відповідей стосуються "справжніх проблем", як обходу дерев, факторіалізмів тощо. Я вважаю за краще "РЕАЛЬНІ реальні проблеми" - дозвольте навести вам приклад ...

У нас був ВЕЛИКИЙ патрон тексту (близько 30 Мб тексту як пов'язаний список structs), і нам потрібно було зробити його індекс для повного пошуку тексту. Нам потрібно було зберігати весь індекс у пам’яті та повторно індексувати текст кожні 10 хвилин.

Кожні 10 хвилин ми б порівнювали весь текст (два пов'язані списки, рядок за рядком) з новоствореним фрагментом тексту - щоб побачити, який рядок було змінено - і тоді ми повторно індексуватимемо лише цей рядок - таким чином нам не вдасться повторно індексувати цілий текст. Пам'ятайте - нам потрібно було знайти точки різниці між двома списками, пов’язаними з 30 Мб.

Один з моїх колег придумав фантастичну програму, яка використовувала ГОЛОВНУ рекурсію для порівняння ліній - а потім збирала позиції, де патрони відрізнялися масивом - так, я знаю, це звучить спантелично - як тут може допомогти рекурсія - але це було.

Справа в тому, - як він міг бачити, що ця проблема може бути вирішена розумно при інтенсивному використанні рекурсії?


Чи справді 30 МБ справді великі, коли більшість комп'ютерів мають ГБ оперативної пам’яті та ТБ місця на жорсткому диску?
JB King

30 МБ НЕ можуть бути великими, але, враховуючи тип структури даних, наш текст був забитий, - це дійсно ВЕЛИКИЙ патрон тексту до ПРОЦЕСУ - та DIFF.
treecoder

3
Не достатньо реально "проходження структури папки"? І я зовсім не бачу на вашому прикладі, як рекурсія повинна бути тут неінтуїтивно зрозумілою, і чому її використання навіть має бути особливо помітним. Ваш колега розробив рекурсивний алгоритм, як і будь-який інший алгоритм. Ви також можете запитати, як Хоаре з'явилася ідея вирішити проблему сортування рекурсивно.
Конрад Рудольф

2
Чи правильно я вважаю, що ви мали на увазі "повторне використання коду" більше як "виконання однієї і тієї ж серії операцій невизначена кількість разів"? Це на відміну від «повторного використання коду» в сенсі написання загального коду для використання в інших місцях.
Енді Хант

4
Але обхід дерев - це "РЕАЛЬНА реальна проблема", з якою багато людей стикаються майже щодня.
Сокіл

Відповіді:


16
  • які "схеми проблем" вимагають вирішення рекурсії

Я б не сказав, що існує така річ, як проблема проблеми використання рекурсії. Кожна функція, яка може бути реалізована за допомогою рекурсії, також може бути реалізована ітераційно, часто шляхом натискання та виведення стека.

Це питання вираження, а також продуктивності. Ітераційні алгоритми часто мають кращу продуктивність і їх легше оптимізувати. Однак рекурсивні алгоритми виграють від більш чіткого вираження, і тому їх часто легше читати, розуміти та реалізовувати.

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

  • це рекурсія, форма стратегії "ділити і перемагай" або форма "повторного використання коду" - або, сама по собі, модель дизайну.

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

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

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


7
"Кожна функція, яка може бути реалізована за допомогою рекурсії, також може бути реалізована ітеративно, часто шляхом натискання та виведення стека." Зрештою, мовами, які використовують пам’ять на основі стека, ви вже натискаєте та виводите дані функції та вимикаєте стек під час використання рекурсії.
JAB

Тільки якщо ви компілюєте або інтерпретуєте мову машиною ;-) Також, з дуже високої точки зору, вираз і мова повністю не залежать від машинного та апаратного забезпечення та ОС, таким чином, не обов'язково є стек.
Сокіл

Ага, так, ви абсолютно праві. Я мав би сказати "в реалізаціях мов / компіляторів мови, які використовують пам'ять на основі стека".
JAB

Взагалі кажучи, ви теж праві. Мені не хотілося з'являтись нахабних.
Сокіл

2
Нескінченні списки можуть бути виражені без рекурсії, принаймні, без рекурсивної реалізації. Генератори Python можуть це зробити, як і генератори в Icon, які, здається, Python запозичили цю ідею. Я вважаю, що F # може зробити цей трюк, хоча я не впевнений. В основному, генератори - це окремий випадок спільних процедур (як кооперативна багатозадачність), які добре підходять для впровадження лінивих списків. Кожен раз, коли генератор "дає" результат, абонент повертається до управління і генератор залишається в режимі очікування, поки не буде запропоновано наступний результат.
Steve314

8

це рекурсія, форма стратегії "ділити і перемагай" або форма "повторного використання коду" - або, сама по собі, модель дизайну.

Ні. Divide & conquer використовує рекурсію. Але рекурсію не обов'язково ділити і перемагати, оскільки остання означає розділити проблему на дві (або більше) частини і вирішити кожну з них симетрично. У рекурсії ви цього не робите.

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

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

Обхід дерева. Або загалом, обхід графіків. Це, зокрема, включає проходження структури папок.

І звичайно все, що використовує ділі & conquer або динамічне програмування, оскільки обидва природно виражаються у вигляді рекурсії.


Динамічне програмування не завжди природно виражається як рекурсія. Насправді динамічне програмування суворо стосується табличних підходів - виключаючи запам'ятовування. Думки, схоже, з цього приводу різняться, але "програмування" в "динамічному програмуванні" насправді є математичним терміном, маючи на увазі табличні підходи (деталь, яку я взяв із курсу алгоритмів відкритого ПЗ 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

Якщо є спосіб спростити його, щоб було легко, це може бути підказкою, що рекурсія могла б спрацювати. Ви можете скористатись сортуванням та пошуком прикладів, де існують рекурсивні рішення, наприклад, сортування об'єднань та двійковий пошук відповідно.

Що слід пам’ятати - це те, як деякі проблеми можна погано вирішити за допомогою рекурсії, як фактор.

Що стосується прикладу реального світу, де я використовую рекурсію, пошук книги з полиці книг можна зробити досить легко рекурсивно. Я просто дивлюся на книгу, і якщо це не те, що я хочу, переходжу до наступної. Я зупиняюся, коли або знаходжу книгу, або потрапляю в кінець рядка. Цикл перевірки книги та перехід до наступної можна зробити рекурсивно. Можливо, це занадто реальний приклад.


2

які "схеми проблем" вимагають вирішення рекурсії

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

це рекурсія, форма стратегії "ділити і перемагай" або форма "повторного використання коду" - або, сама по собі, модель дизайну.

Жодні з вищезазначених. Це просто спосіб зробити те ж саме повторно, іноді заснований на варіаціях на вході. Концепція існує набагато довше, ніж зразки дизайну, повторного використання коду або навіть комп’ютерів.

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

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


-1

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

Це те, що відбувається у функціональному програмуванні. Насправді ви вказуєте, що (визначення), а не як . Іншими словами, ви визначаєте базу, а потім визначаєте свою проблему в терміні субпроблеми.

Наприклад, розглянемо Factorialалгоритм

  • Визначте основу: Факторний (1) = 1;
  • Визначте Факторний n: Факторний (n) = n * Факторний (n-1);

Тоді, коли ви зіткнулися з проблемою, вам слід подумати, чи можете ви визначити її рекурсивно чи ні, якщо ви можете визначити її рекурсивно, ви майже вирішили її.

Однак будь-яка рекурсивна функція не повинна бути рекурсивним визначенням. Можна визначити базу і співвіднести (визначити) рішення основної задачі з рішенням (визначенням) підзадач. Але для цього відношення вам може знадобитися процедура.

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

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.