Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
РЕКУРСИЯ1_Лекция15.docx
Скачиваний:
0
Добавлен:
01.03.2025
Размер:
94.97 Кб
Скачать

16.Рекурсия. Рекурсивные алгоритмы.

Рекурсивный алгоритм – это алгоритм, который при выполнении вызывает самого себя. Такой алгоритм оформляется всегда в виде некоторого вспомогательного алгоритма (ВА), в С++ – это функция.

Рекурсивным может быть определение: например, натуральное число- это либо 1, либо целое число, следующее за натуральным.

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

1, при N=0

FACT(N)=

N * FACT(N-1), при N>0

В С++ рекурсивный алгоритм оформляется в виде функции, назовём её P( ). Если эта функция вызывает сама себя P=>P, то она наз. пряморекурсивной. Вызов может быть и опосредованным P=>Q1=>Q2=>...=>QN=>P, в этом случае говорят: Pкосвенно-рекурсивная.

Рассмотрим пример: описание функции N!

unsigned int fact (unsigned int N)

{ if (N==0) return 1;

return N* fact ( N-1);

}

Обратите внимание, что алгоритм содержит некоторую группу S предложений, которые не содержат рекурсивный вызов, и группу, где есть обращение к самому себе, т.е. P =P (S, P). При создании рекурсивного алгоритма необходимо заботиться, чтобы цепь рекурсивных вызовов не была бесконечной. Для этого рекурсивный вызов подчиняют условию: P = P ( S, if (условие) P )

Проще всего рекурсивный вызов связать с некоторым параметром n, на каждом шаге этот параметр уменьшать:

P(n) =P (S, if(n>0) P(n-1))

пока не станет n=0, происходит вызов P().

Рассмотрим выполнение алгоритма fact (3). Это функция, у неё один формальный параметр N, других локальных переменных нет. Вызов функции начинается с того, что в некоторой области памяти- в стеке- выделяется место под формальные параметры и локальные переменные (их вместе называют локальными переменными функции), затем выполняется алгоритм функции, он вызывает снова эту функцию для параметра (N-1), и т.д. для каждого вызова создаётся своё поколение лок. данных в стеке по принципу LIFO, доступно всегда верхнее поколение.

fact(3) => fact(2) => fact(1) ) => fact(0)рекурсивный спуск

(N=3)*2=6 | <=(N=2)*1=2 | <= (N=1)*1=1 | <= 1 -рекурсивный возврат

N=0

N=1

N=2

N=3

1 2 3 4 - уровни рекурсии

  • поколения локальных данных

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

Создаваемая цепь рекурсивных вызовов наз. рекурсивный спуск.

fact(0) не выполняет нового вызова, а возвращает значение 1 на предыдущий уровень, там N*1 и это значение возвращается на предыдуший вызов и т.д. Т.О. происходит возврат по цепочке обратно , его наз. рекурсивный возврат.

Цепь рекурсивных вызовов закончится, если станет n=0 и начнётся рекурсивный возврат.

Выводы. Для корректной организации рекурсивного алгоритма необходимо: