3.2. Приклади рекурсивних алгоритмів
Приклад 1. Рекурсивний метод Countdown(5) виводить на консоль послідовність чисел від 5 до 0.
class Program
{
public static void Main(string[] args)
{
Countdown(5);
Console.ReadKey();
}
private static void Countdown(int i)
{
Console.WriteLine(i);
// базовий випадок
if (i <= 0) return;
// рекурсивний випадок
Countdown(i - 1);
}
}
Як видно з прикладу, метод CountDown викликає сам себе до тих пір, поки змінна i не стане <=0. Зверніть увагу, що циклу в цьому методі немає.
Серед найбільш поширених рекурсивних алгоритмів можна назвати:
1. Обчислення факторіала N!
, де
2. Обчислення чисел Фібоначчі, що задається формулами:
F(1)=1,F(2)=1;F(3)=2, F(n+1)=F(n)+F(n-1)
Приклад 2. Знаходження факторіалу цілого числа
public class Program
{
//Рекурсивний алгоритм
public static long factorial(int n)
{
if (n <= 1) return 1; //базовий випадок
else return n * factorial(n - 1); //рекурсивний
} //factorial
//Не рекурсивний алгоритм
public static long fact(int n)
{
long res = 1;
for (int i = 2; i <= n; i++) res *= i;
return (res);
} //fact
Знаходження чисел Фібоначчі
Числа Фібоначчи — елементи числової послідовності
0, 1, 1, 2, 3, 5, 8, 13, 21, 34, 55, 89, 144, 233, 377, 610, 987, 1597, 2584, 4181, 6765, 10946
у якій кожне наступне число дорівнює сумі двох попередніх чисел. Формально послідовність чисел Фібоначчі задається лінійним рекурентним співвідношенням:
F(1)=1,F(2)=1;F(3)=2, F(n+1)=F(n)+F(n-1)
Простий нерекурсивний алгоритм генерації чисел Фібоначчі розглядався у лекції 2:
Під час виконання рекурсивної підпрограми в оперативній пам'яті виділяється місце для даних процедури або функції, яка викликається. І ті підпрограми, які рекурсивно передають управління, залишаються в оперативній пам'яті. Тому завершення підпрограм відбувається покроково, в зворотному порядку.
Приклад 4. Нерекурсивний алгоритм на мові C#
static void Main(string[] args)
{
int a = 1;
int b = 1;
int c = 0;
Console.WriteLine("Введіть кількість чисел послідовності");
int n = int.Parse(Console.ReadLine());
Console.WriteLine("Перше число = " + a);
Console.WriteLine("Друге число = " + b);
for (int i = 2; i < n; i++)
{
c = a + b;
Console.WriteLine("Наступний член ряду= " + c);
a = b;
b = c;
}
Console.ReadKey();
}
Рекурсивний алгоритм на мові С#
namespace Recursia
{
class Program
{
static int fibon(int i)
{
if (i == 0) return 1; //базовий випадок
if (i == 1) return 1; // базовий випадок
if (i < 0) return 0; // базовий випадок
return fibon(i - 2) + fibon(i - 1); //рекурсивний випадок
}
static void Main(string[] args)
{
int f;
Console.WriteLine("Введіть n");
int i = int.Parse(Console.ReadLine());
f = fibon(i);
Console.WriteLine("Fibonnachi is " + f);
Console.ReadKey();
}
}
}
Таким чином, видно, що будь-яку рекурсію можна замінити циклом і допоміжною змінною в пам’яті.