Любая концепция, которую мы не полностью понимаем, могут быть страшно сначала.
Рекурсия – это тема, которую ученики программирования не учатся прямо сейчас. Но это не значит, что это должно быть страшно или вызывает беспокойство.
На самом деле, рекурсия – это концепция, которую мы можем довольно просто определить.
По словам Википедия :
И вы можете применить рекурсию в свой код, создавая функцию, которая вызывает сама.
Любая функция с циклом может быть рекурсивной вместо
Вот функция называется CountToten что использует цикл While для регистрации каждого числа от одного до десяти:
const countToTen = (num = 1) => {
while (num <= 10) {
console.log(num);
num++;
}
}
countToTen();
Мы можем написать ту же функцию с рекурсией вместо петли.
Обратите внимание, что рекурсивные функции имеют две части:
- Функция вызывает себя (также известна как рекурсивный вызов)
- По меньшей мере, одно условие для выхода из рекурсии (также известно как базовый случай)
const countToTen = (num = 1) => {
if (num > 10) return; //base case
console.log(num);
num++;
countToTen(num); //recursive call
}
countToTen();
Это не сказать, что мы Должен всегда Замените петли с рекурсией.
Есть случаи, где использование рекурсии – лучший выбор – и также есть случаи, где это не лучший выбор.
Зачем использовать рекурсию
Давайте посмотрим на некоторые причины использования рекурсии. Мы увидим некоторые примеры ниже.
Меньше строк кода
Применение рекурсии обычно приводит к решению с меньшим количеством линий кода, чем решение, которое не использует рекурсию.
Более элегантный код
В дополнение к меньшему количеству строк кода, рекурсивные решения, как правило, больше приятят. Другими словами, рекурсивные решения обычно считаются элегантными.
Повышенная читаемость
Причины 1 и 2 обычно объединяются для создания причины 3, которая является повышенной читаемостью вашего кода. Помните, мы не пишем код только для себя. Мы пишем код для разработчиков, которые следуют нами и должны понимать наш код.
Причины не использовать рекурсию
Убытки производительности
Повторяющиеся вызовы функций не так эффективны или исполнителю, как нанесение цикла. Мы не хотим просто выбрать рекурсию, потому что мы можем.
Проблемы отладки
Логика рекурсии не всегда легко следовать. Использование рекурсии может сделать ваш код более трудным для отладки.
Улучшена ли читабельность?
Увеличение читаемости не гарантируется путем использования рекурсии. На самом деле это может по мнению и/или ситуации. Вы должны оценить читаемость, и если это не улучшено, рекурсия не может быть лучшим ответом.
Примеры рекурсии
Проблемы рекурсии – это фавориты интервью.
Одна такая проблема просит функцию, которая возвращает х Номера последовательности Фибоначчи.
Последовательность Фибоначчи добавляет два предыдущих количества последовательности для создания следующего номера в последовательности. Вот первые десять номеров последовательности: The Fibonacci sequence adds the two previous numbers of the sequence to create the next number in the sequence. Here are the first ten numbers of the sequence:
Мы можем написать эту функцию без рекурсии:
const fibonacci = (num = 2, array = [0, 1]) => {
while (num > 2) {
const [nextToLast, last] = array.slice(-2);
array.push(nextToLast + last);
num -= 1;
}
return array;
}
console.log(fibonacci(10));
И вот рекурсивная версия той же функции:
const fibonacci = (num = 2, array = [0, 1]) => {
if (num < 2) return array.slice(0, array.length - 1);
const [nextToLast, last] = array.slice(-2);
return fibonacci(num - 1, [...array, nextToLast + last]);
}
console.log(fibonacci(10));
Рекурсивная функция имеет меньше строк кода. Но я не уверен, что мы можем уверенно сказать, что это увеличило элегантность или читаемость.
Давайте посмотрим на другую проблему, где рекурсия оказывает большее влияние.
Другое избранное интервью просит функцию, которая возвращает N-й номер в последовательности FIBONACCI. Следовательно, если функция получает 10 Как параметр, он должен вернуть 34 Отказ
Без использования рекурсии возможное решение выглядит так:
const fibonacciPos = (pos = 1) => {
if (pos < 2) return pos;
const seq = [0, 1];
for (let i = 2; i <= pos; i++) {
const [nextToLast, last] = seq.slice(-2);
seq.push(nextToLast + last);
}
return seq[pos];
}
console.log(fibonacciPos(10));
Однако с рекурсией решение намного меньше и, возможно, более элегантно:
const fibonacciPos = (pos = 1) => {
if (pos < 2) return pos;
return fibonacciPos(pos - 1) + fibonacciPos(pos - 2);
}
console.log(fibonacciPos(10));
Вау! Это сделало огромное значение.
Обратите внимание, как линия возврата фактически вызывает функцию дважды.
Вы понимаете логику в этих рекурсивных функциях? Если нет, провести некоторое время экспериментировать с ними, чтобы понять, как они работают. После того, как вы сделаете, вы, вероятно, согласитесь, что читабельность также улучшается.
Чтобы подчеркнуть, насколько улучшена читаемость, давайте посмотрим на ту же рекурсивную функцию сверху, написанную в одной строке (линия может завернуть в вашем браузере, но это одна строка кода):
const fibonacciPos= pos => pos < 2 ? pos : fibonacciPos(pos - 1) + fibonacciPos(pos - 2); console.log(fibonacciPos(10));
Наше оригинальное рекурсивное решение вышло с четырех строк кода только к одному!
Это более читается для вас? Вы все еще следуете за логикой позади этого?
Ваш ответ будет зависеть от вашего текущего уровня понимания. Однострочное решение использует тройное утверждение, имеет функцию стрелки без скобок, которые также подразумевают оператор возврата и применяет рекурсию как раньше.
Я обычно не пишу функции, такие как одно строчное решение выше, потому что я часто участвую в начале курсов веб-разработки. Поэтому я часто разбиваю свой код в преднамеренные шаги, которые легче следовать.
Это не значит, что есть что-то не так с одним линейным решением выше.
Фактически, функция элегантна, читаемая и высокоэффективна, если вы понимаете логику за ним.
Если вы работаете над командой, ваша команда может иметь гид стиля. Если одна функция строки предпочтительна, когда это возможно, пойти на него! Если предпочтительнее более преднамеренное, пошаговое стиль, следуйте своему руководству. Эти решения совершенно ситуационные.
Вывод
Рекурсия может показаться страшной, но это не должно быть.
Мы можем сломать концепцию рекурсии до простого определения.
Не обладайте силой рекурсии только потому, что вы можете.
Вы должны основывать решение использовать рекурсию в вашем коде при эффективности, производительности, элегантности и читабельности.
Вам может быть интересно, где рекурсия может быть применена в «реальном мире» вместо того, чтобы просто ответить на вопросы интервью на последовательности FIBONACCI.
Я оставлю вас с учебником с моим каналом YouTube. Я не только глубже посмотрите на примеры выше, но я также раскрываю некоторые экземпляры «реального мира», где применяя рекурсию – лучший выбор: