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

7. Рекурсивные функции.

Рекурсия в программировании — задание алгоритма вычисления функции с использованием вызова её самой.

пример:

inv::[a]->[a]

inv[]=[]

inv(x:xs)=inv xs ++ [x]

8. Проблема выбора подфункции

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

От удачного решения проблемы выбора подфункции зависит эффективность программы в целом.

Функция инверсия списка.

x

обратить(x)

(ABС)

(СВА)

((AB)(CD))

((CD)(АВ))

NIL

NIL

Для решения необходимо иметь функцию, которая могла бы поместить голову списка car (x) в конец рекурсивного вызова обратить (cdr (x))

добавить (x,y) – делает у новым послед. элементом х

x

у

добавить (x,y)

(AB)

С

(АВС)

Обратить (х)

1. х = NIL обратить (x)=NIL

2. х ≠ NIL , пусть обратить (cdr(x))=z, тогда обратить (х)=добавить (z,cdr(x))

1) обратить (х) = если равно (x,NIL) то NIL иначе добавить (обратить (cdr (x),car (x))

Добавить (х)

1. х = NIL добавить (x,y)=cons (y,NIL)

2. х ≠ NIL , пусть добавить (cdr(x),y)=z, тогда добавить (х,y)=cons (car (x),z)

1) добавить (x,y) ≡ если равно (x,NIL) то cons (y,NIL) иначе cons (car (x), добавить (cdr (x),y)

2) добавить (x,y) ≡ соединить (x, cons (y,NIL))

cons (y,NIL) – [y]

3) обратить (х) ≡ если равно (x,NIL) то NIL иначе соединить (обратить (cdr (x)), cons (car (x), NIL))

Например, задача разбиения предложения на слова и подсчет количества повторения каждого

можно разбить на функции по шагам:

разбиение на слова

удаление повторений слова, количество вхождений которого уже подсчитано

формирование массива кортежей (слово, колич вхождений)

забыла там еще - непосредственно функция подсчета повторений слова

то есть 4 функции

а можно например по другому:

1разбиваем на слова ,

2 считаем колич вхождений и сразу удаляем повторения для посчитанного слова, и выводим кортеж для конкретного слова (слово, колич вхождений)

итого 2 функции

9. Накапливающий параметр — аккумулятор

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

обратить (х)

обр (x,y), где х – инвертируемый список, у – параметр, накапливающий инвертированный список.

х :: [1,2,3,4,5] – начальн.

y:: [ ]

х :: [1,2,3,4,5] – 1 шаг

y:: [ ]

х :: [2,3,4,5] – 2 шаг

y:: [1]

х :: [3,4,5] – 3 шаг

y:: [ 2,1]

х :: [4,5] – 4 шаг

y:: [3,2,1]

обр (x,y) ≡ если равно (x,NIL) то y иначе обр (cdr (x), cons (car (x),y)

обратить (x) ≡ обр (x,NIL)

Применим метод накапливающих параметров в случае, когда необходимо накопить более чем 1 результат.

Бывает так, что при выполнении функции исключительно сёрьезно встаёт проблема расхода памяти. Эту проблему можно пояснить на примере функции, вычисляющей факториал числа:

Если провести пример вычисления этой функции с аргументом  , то можно будет увидеть следующую последовательность:

==> 

==> 

==> 

==> 

==> 

==> 

==> 

На примере этого вычисления наглядно видно, что при рекурсивных вызовах функций очень сильно используется память. В данном случае количество памяти пропорционально значению аргумента, но аргументов может быть большее число. Возникает резонный вопрос: можно ли так написать функцию вычисления факториала (и ей подобные), чтобы память использовалась минимально?

Чтобы ответить на данный вопрос положительно, необходимо рассмотреть понятие аккумулятора (накопителя). Для этого можно рассмотреть следующий пример:

Пример 10. Функция вычисления факториала с аккумулятором.

В этом примере второй параметр функции   выполняет роль аккумулирующей переменной, именно в ней содержится результат, который возвращается по окончании рекурсии. Сама же рекурсия в этом случае принимает вид «хвостовой», память при этом расходуется только на хранение адресов возврата значения функции.

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