Следующая: recursion2, Предыдущая: seq, Вверх: Top
Эпиграф: void ShortStory() { cout<<"У попа была собака, он ее любил."<<endl; cout<<"Она съела кусок мяса, он ее убил,"<<endl; cout<<"В землю закопал и надпись написал:"<<endl; ShortStory(); }
Функции в современных языках программирования могут вызывать другие функции. Но функция также может вызывать и саму себя! Рассмотрим это на примере функции вычисления факториала. Хорошо известно, что 0!=1, 1!=1. А как вычислить величину n! для большого n? Если бы мы могли вычислить величину (n-1)!, то тогда мы легко вычислим n!, поскольку n!=n(n-1)!. Но как вычислить (n-1)! ? Если бы мы вычислили (n-2)!, то мы сможем вычисли и (n-1)!=(n-1)(n-2)!. А как вычислить (n-2)! ? Если бы... В конце концов, мы дойдем до величины 0!, которая равна 1. Таким образом, для вычисления факториала мы можем использовать значение факториала для меньшего числа. Это можно сделать и в программе на C++ или Питоне:
// C++ int factorial (int n) { if (n==0) return 1; else return n*factorial(n-1); } # Python def factorial (n): if n==0: return 1 else: return n*factorial(n-1)
Подобный прием (вызов функцией самой себя) называется рекурсией, а сама функция называется рекурсивной.
Рекурсивные функции являются мощным механизмом в программировании. К сожалению, они не всегда эффективны (об этом речь пойдет позже). Также часто использование рекурсии приводит к ошибкам, наиболее распространенная из таких ошибок – бесконечная рекурсия, когда цепочка вызовов функций никогда не завершается и продолжается, пока не кончится свободная память в компьютере. Пример бесконечной рекурсии приведен в эпиграфе к этому разделу. Две наиболее распространенные причины для бесконечной рекурсии:
if (n==0)
, то factorial(0)
вызовет factorial(-1)
,
тот вызовет factorial(-2)
и т.д.
factorial(n)
будет
вызывать factorial(n)
, то также получиться бесконечная цепочка.
Поэтому при разработке рекурсивной функции необходимо прежде всего оформлять условия завершения рекурсии и думать, почему рекурсия когда-либо завершит работу.
при n>1. Начало ряда Фибоначчи выглядит следующим образом: 1, 1, 2, 3, 5, 8, 13, 21, 34, 55, ...
Напишите функцию int phi(int n)
, которая по данному натуральному n
возвращает φn.
Напишите программу, которая решает головоломку – для данного числа дисков n
печатает последовательность перекладываний в формате
"Диск 1 переложить с колышка 1 на колышек 2"
.
Диски пронумерованы числами от 1 до n в порядке возрастания диаметров.
Указание: подумайте, как переложить пирамидку из одного диска? Из двух дисков?
Из трех дисков? Из четырех дисков? Напишите функцию move (n, x, y)
, которая
печатает последовательность перемещаемых дисков для перекладывания пирамидки высоты n
с колышка номер x
на колышек номер y
.