Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
I_semestr.doc
Скачиваний:
6
Добавлен:
23.09.2019
Размер:
356.35 Кб
Скачать

Глава 13. Рекурсия

13.1. Понятие рекурсии

Рекурсия – это процесс повторения чего-либо самоподобным образом.

Рекурсия – способ определения множества объектов через самого себя с использованием ранее заданным частных определений. Из математики примером является референтное определение списка: список – совокупность элементов (голова списка) и еще одного списка (хвост) или пустой список.

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

Глубиной рекурсии называют количество рекурсивных вызовов.

Граничные условия рекурсии – такие значения аргумента, при которых заранее известно решение рекурсивной функции.

Пример бесконечной рекурсии: у попа была собака…

Зацикливание от бесконечной рекурсии отличается тем, что при зацикливании не задействуются дополнительные ресурсы, а при бесконечной рекурсии будет переполнение стека.

Прямой рекурсией называют рекурсию, в которой функция вызывает саму себя (простая рекурсия)

Косвенная (сложная) рекурсия – способ определения рекурсивной функции, при котором она вызывается рекурсивно другой функцией, т.е. косвенно.

Хвостовая рекурсия – способ объединения рекурсивной функции, при котором рекурсивный вызов происходит в самом конце ее тела.

Порядок рекурсии – количество рекурсивных вызовов на одном уровне глубины рекурсии.

13.2. Вычисление факториала

n! – произведение всех натуральных чисел от 1 до n включительно.

Это обычное, не рекуррентное определение

=(1*2*3*…*(n-1))*n = (n-1)!*n, n>1. Если n=0, 0!=1. Если n=1, 1!=1.

long fact(unsigned n)

{

if(n<2)

return 1;

return n*fact(n-1);

}

Вычислить факториал можно и без рекурсии:

long fact1(unsigned n)

{

unsigned i,y;

for(i=1,y=1;i<=n;i++)

y*=i;

return y;

}

long fact2(unsigned n)

{

unsigned y;

while (n>0)

{

y*=n;

n--;

}

}

13.3. Числа Фибоначчи

unsigned long Fib(unsigned i)

{

if (i<2) return 1;

return Fib(i-1)+Fib(i-2);

}

unsigned long Fib2(unsigned n)

{

unsigned i;

unsigned long f1,f2;

while(i<=n)

{

f2=f1+f2;

f1=f;

i++;

}

}

5!

Fact(5)

5*Fact(4)

4*Fact(3)

3*Fact(2)

2*Fact(1)

1

Fib(5)

Fib(4)+Fib(3)

Fib(3)+Fib(2) Fin(2)+Fib(1)

Fin(2)+Fib(1) Fib(1)+Fib(0)

13.4. Замена итерационных алгоритмов рекурсивными

Рассмотрим алгоритм, выводящий числа через одно в указанных пределах.

for(i=from;i<to;i++)

printf(“%d “,i)

Опишем рекурсивную функцию, выполняющую аналогичное действие:

void Count(int from, int to)

{

printf(“%d “,from);

if(from<to)

Count(from+1,to);

}

Count(1,5)

1 Count(2,5)

2 Count(3,5)

3 Count(4,5)

4 Count(5,5)

5

Преобразуем рекурсию в хвостовую.

void Count(int from, int to)

{

printf(“%d “,from);

if(from>=to)

return;

Count(from+1,to);

}

Составим функцию обратного отчета:

void CountDown(int from, int to)

{

printf(“%d “,from);

if(to>=from)

return;

CountDown(from-1,to);

}

void CountDown(int min, int max)

{

if(min<max)

CountDown(min+1,max);

printf(“%d “,&min);

}

Для последней функции стек вызовов будет выглядеть следующим образом:

CD(1,5)

CD(2,5)

CD(3,5)

CD(4,5)

CD(5,5)

printf(5)

printf(4)

printf(3)

printf(2)

printf(1)

Соседние файлы в предмете [НЕСОРТИРОВАННОЕ]