
- •1.2. Правила записи программ на языке с
- •1.3 Правила формального описания синтаксиса языка программирования
- •1.5.3. Описание данных в языке с
- •1.5.4 Правила записи констант различных типов
- •1.5.5. Символьные строки
- •Глава 2. Понятие функции
- •2.1. Стандартная функция printf
- •2.2. Стандартная функция scanf
- •Перед каждым аргументом, не являющимся строкой (адресом) ставится знак & и трактуется как вычисление адреса.
- •2.3. Стандартные математические функции
- •2.4. Простейшие функции, определяемые программистом
- •3.5. Дополнительные арифметические операции
- •3.6. Дополнительные операции присваивания
- •3.7. Битовые операции
- •3.8. Операторы отношения
- •Глава 4. Структурное программирование и язык с
- •4.2. Операторы языка с
- •4.3. Оператор цикла while
- •4.4. Оператор цикла do – while (цикл с постусловием)
- •4.5. Условный оператор и условная операция
- •4.6. Оператор цикла for (цикл с известным числом повторений)
- •4.7. Запись алгоритмов при помощи диаграмм Несси-Шнейдермана
- •4.8. Оператор прерывания цикла
- •4.9. Оператор продолжения цикла (continue)
- •4.10. Множественный выбор
- •Глава 5. Типовые приемы в программировании
- •5.1. Использование счетчиков
- •5.2. Вычисление суммы и произведения.
- •5.3. Вычисление минимума и максимума последовательностей.
- •5.4. Использование флагов
- •Глава 6. Простейшая графика
- •6.1.Графические режимы
- •6.2. Идеология bgi и WinBgi
- •6.3.Основные графические функции
- •6.3.1. Управление графическими режимами
- •6.3.2. Графические примитивы
- •6.3.3. Установки и их проверка
- •6.3.4. Работа с текстом
- •Глава 7. Модульное программирование
- •7.2. Библиотеки функций
- •Глава 8. Массивы
- •8.1. Описание массива
- •8.2. Ввод – вывод массивов
- •8.3. Инициализация массива
- •8.6. Двумерные массивы
- •8.6.1. Инициализация двумерного массива
- •8.7. Многомерные массивы
- •Глава 9. Работа с файлами
- •9.1. Открытие и закрытие файлов
- •Глава 10. Структуры языка с
- •10.1. Описание структур
- •10.2. Трактовка имени структуры
- •10.2.1. Доступ к полям структуры
- •10.3. Инициализация структур
- •10.4. Структуры и функции
- •10.5. Поля бит в структурах
- •10.6. Объединение
- •Глава 11. Дополнительные сведения о функциях
- •11.1. Области видимости.
- •Глава 12. Анимация
- •Глава 13. Рекурсия
- •13.1. Понятие рекурсии
- •13.2. Вычисление факториала
- •13.3. Числа Фибоначчи
- •13.4. Замена итерационных алгоритмов рекурсивными
- •13.5. Применение рекурсии в графике
Глава 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)