Найти в Дзене

Грокаем алгоритмы. Рекурсия. Часть 5

Заметки:

  1. Рекурсия — метод вызывает сам себя. Решение с рекурсией становится более понятным.
  2. Цитата Ли Колдуэлла (https://stackoverflow.com/questions/72209/recursion-or-iteration/72694#72694): "Циклы могут ускорить работу программы. Рекурсия может ускорить работу программиста. Выбирайте, что важнее в вашей ситуации".
  3. Рекурсия не ускоряет работу. Решение с циклами иногда работает быстрее. По памяти циклы выгодней.
  4. С рекурсией легко ошибиться и написать метод так, что возникнет бесконечный цикл. Поэтому рекурсивный метод ВСЕГДА состоит из базового случая и рекурсивного.
  5. Базовый случай — вариант, когда функция себя НЕ вызывает, чтобы не было бесконечного цикла.
  6. Рекурсивный случай — функция вызывает сама себя.
https://gist.github.com/Ladgertha/2cc5f500821f64a581f2f14622e7a257
https://gist.github.com/Ladgertha/2cc5f500821f64a581f2f14622e7a257

Стек:

  1. Стек — это как стопка листков. Новые листочки мы кладем только сверху. И берем тоже сверху.
  2. В стеке всего два действия: вставка (кладем листок) и чтение (достаем листок).
  3. Для методов используется стек вызовов и все методы кладутся в этот стек.
    Например, есть у нас метод fun addName() { val name = getName() }. При вызове addName() выделяется блок памяти для этого метода. Там будут храниться все переменные и их значения. Когда доходим до метода getName(), то он кладется сверху на метод addName в памяти (прям как лист бумаги). При завершении метода getName он выкидывается из памяти. Но получается, что во время работы getName, метод addName всё ещё существует и не завершен. Он занимает своё место в памяти.
  4. Когда мы вызываем метод из другого метода, то вызывающий метод приостанавливается в частично завершенном состоянии. :)
  5. Рекурсивные функции используют стек вызовов.
  6. Попробуем вычислить факториал через рекурсию. Напомню, что факториал — произведение всех предыдущих чисел, включая текущее, но исключая 0. Например, факториал для 3 = 3 * 2 * 1 = 6.
https://gist.github.com/Ladgertha/e045ded742d1e899a832f6a126a0420e
https://gist.github.com/Ladgertha/e045ded742d1e899a832f6a126a0420e

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

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