Рубрики
Без рубрики

Как работает рекурсион – объяснено с блок-схемами и видео

Иллюстрация (и все в этой статье) путем Adit Bhargava “для того, чтобы понять рекурсию, нужно сначала понять рекурсию. «Рекурсия может быть трудно понять – особенно для новых программистов. В его простейшей форме рекурсивная функция – это то, что называет себя. Позвольте мне попытаться объяснить с примером. Представлять себе

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

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

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

Существует два основных подхода для создания алгоритма этой проблемы: итеративные и рекурсивные. Вот оба подхода как таблицы потоков:

Какой подход вам кажется легче?

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

function look_for_key(main_box) {
    let pile = main_box.make_a_pile_to_look_through();
    while (pile is not empty) {
        box = pile.grab_a_box();
        for (item in box) {
            if (item.is_a_box()) {
                pile.append(item)
            } else if (item.is_a_key()) {
                console.log("found the key!")
            }
        }
    }}

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

function look_for_key(box) {
  for (item in box) {
    if (item.is_a_box()) {
      look_for_key(item);
    } else if (item.is_a_key()) {
      console.log("found the key!")
    } 
  }
}

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

Также, поскольку много алгоритмов используют рекурсию, важно понять, как это работает. Если вам все еще не кажется простой, не волнуйтесь: я собираюсь поехать еще несколько примеров.

Базовый чехол и рекурсивный случай

То, что вы должны выбрать при написании рекурсивной функции, является бесконечной петлей. Это когда функция продолжает звонить себе … и никогда не останавливается называть себя!

Например, вы можете захотеть написать функцию подсчета. Вы можете написать это рекурсивно в JavaScript, как это:

// WARNING: This function contains an infinite loop!
function countdown(i) {  console.log(i)  countdown(i - 1)}

countdown(5);    // This is the initial call to the function.

Эта функция продолжит подсчитывать навсегда. Если вы случайно выполните код с бесконечной петлем, вы можете нажать «Ctrl-C», чтобы убить ваш сценарий. (Или, если вы иногда используете код, как я, вам нужно добавить в конец URL.)

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

Вот функция обратного отсчета снова, с базовым случаем:

function countdown(i) {
    console.log(i)  if (i <= 1) {  // base case
        return;
    } else {     // recursive case
        countdown(i - 1);
    }
}

countdown(5);    // This is the initial call to the function.

Может не быть очевидно, что именно происходит в этой функции. Я пройду через то, что произойдет, когда вы называете функцию обратного отсчета, проходящие в «5».

Мы начинаем с распечатывания номера 5, используя console.log Отказ С пятью не меньше или равно нулю, мы идем к другому утверждению. Там мы снова называем функцию обратного отсчета с номером четыре?).

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

Стек вызова

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

Я покажу вам стек вызова в действии с факториал функция. факториал (5) написано как 5! И это определено так: * 4 * 3 * 2 * 1. Вот рекурсивная функция для расчета факториала ряд:

function fact(x) {
    if (x == 1) {
        return 1;
    } else {
        return x * fact(x-1);
    }
}

Теперь посмотрим, что произойдет, если вы позвоните факт (3) На рисунке ниже показано, как стек меняется, линия по линии. Самая верхняя коробка в стеке говорит вам, какой звонок на факт Вы сейчас находитесь.

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

Вы уже нашли ключ?

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

Но в рекурсивом подходе нет кучи. Как ваш алгоритм знает, какие коробки вам все еще должны посмотреть? «Куча коробок» сохраняется на стеке. Это стек из полузавершенных полученных функций звонков, каждый с собственным полупроцентом списка коробок для просмотра. Стог отслеживает кучу коробок для вас!

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

Вы также можете посмотреть это 5-минутное видео, которое я сделал о рекурсии. Это должно усилить эти концепции рекурсии.

Заключение

Я надеюсь, что эта статья принесла вам больше ясности о рекурсии в программировании. Эта статья основана на уроке в моем новом видеоскохозяйственном курсе от Manning Publications под названием Алгоритмы в движении Отказ Курс (а также эта статья) основан на Удивительно книга Гроккинг алгоритмы Adit Bhargava. Он тот, кто нарисовал все веселые иллюстрации в этой статье.

Если вы узнаете лучше всего через книги, Получить книгу Действительно Если вы узнаете лучше всего с помощью видео, рассмотрим Покупая мой курс Отказ

И, наконец, чтобы по-настоящему понять рекурсию, вы должны снова прочитать эту статью. ?

Оригинал: “https://www.freecodecamp.org/news/how-recursion-works-explained-with-flowcharts-and-a-video-de61f40cb7f9/”