Silnia

Zacznijmy od algorytmu wyznaczania silnisilniasilni z liczby naturalnej. Zastosujemy w pseudokodzie rekurencję – funkcja będzie wywoływała samą siebie aż do momentu dojścia do przypadku podstawowegoprzypadek podstawowyprzypadku podstawowego. Przy pisaniu pseudokodu pomocna okaże się definicja rekurencyjna silni.

n ! = { 1 gdy  n = 0 ( n - 1 ) ! n gdy  n > 0

Zgodnie z tą definicją funkcja będzie wywoływała samą siebie z parametrem zmniejszonym o 1, aż do momentu, gdy n będzie równe 0 – wtedy zostanie zwrócona wartość 1. Pseudokod funkcji rekurencyjnej realizującej algorytm wyznaczania silni liczby naturalnej n wygląda następująco:

Linia 1. funkcja silnia otwórz nawias okrągły n zamknij nawias okrągły. Linia 2. jeżeli n znak równości znak równości 0 wykonaj dwukropek. Linia 3. zwróć 1. Linia 4. w przeciwnym razie wykonaj dwukropek. Linia 5. zwróć silnia otwórz nawias okrągły n minus 1 zamknij nawias okrągły asterysk n.
Ćwiczenie 1

Zastanówmy się, jaki będzie schemat kolejnych wywołań rekurencyjnych w przypadku wyznaczenia silni liczby 6.

Najpierw będą rekurencyjnie wywoływane funkcje z coraz mniejszymi wartościami, czyli 5, 4, 3, 2, 1, aż dojdziemy do 0. Wtedy nastąpi zwrócenie wartości 1 i zaczniemy po kolei wychodzić z zagnieżdżenia wywołań funkcji, za każdym razem zwracając wynik danej silni. Na koniec osiągniemy szukaną wartość 6!:

R123ixfSk5c87
Źródło: Contentplus.pl Sp. z o.o., licencja: CC BY-SA 3.0.

Wyraz ciągu rekurencyjnego

Ćwiczenie 2

Napiszmy funkcję funkcja(n) przyjmującą parametr naturalny n, która w przypadku n parzystego zwróci funkcja(n‑2) --- 3, natomiast w przypadku n nieparzystego zwróci funkcja(n‑1) mod 9. Dodatkowo dla n < 2 zawsze powinna zostać zwrócona wartość 122.

a n = { 122 gdy  n < 2 a n 2 3 gdy  n   m o d   2 = 0 a n 1   m o d   9 gdy  n   m o d   2 0

Rozpocznijmy od warunku, który mówi o tym, że dla n mniejszego od 2 zwracana jest wartość 122.

Linia 1. funkcja funkcja otwórz nawias okrągły n zamknij nawias okrągły. Linia 2. jeżeli n otwórz nawias ostrokątny 2 wykonaj dwukropek. Linia 3. zwróć 122.

Natomiast jeżeli n NIE JEST mniejsze od 2, musimy sprawdzić, czy n jest liczbą parzystą, i umieścić odpowiednie instrukcje w przypadku spełnienia tego warunku.

Linia 1. funkcja funkcja otwórz nawias okrągły n zamknij nawias okrągły. Linia 2. jeżeli n otwórz nawias ostrokątny 2 wykonaj dwukropek. Linia 3. zwróć 122. Linia 4. w przeciwnym razie wykonaj dwukropek. Linia 5. jeżeli n procent 2 znak równości znak równości 0 wykonaj dwukropek. Linia 6. zwróć funkcja otwórz nawias okrągły n‑2 zamknij nawias okrągły minus 3.

Jeżeli n nie jest liczbą parzystą, musimy zwrócić funkcja(n‑1) mod 9.

Linia 1. funkcja funkcja otwórz nawias okrągły n zamknij nawias okrągły. Linia 2. jeżeli n otwórz nawias ostrokątny 2 wykonaj dwukropek. Linia 3. zwróć 122. Linia 4. w przeciwnym razie wykonaj dwukropek. Linia 5. jeżeli n procent 2 znak równości znak równości 0 wykonaj dwukropek. Linia 6. zwróć funkcja otwórz nawias okrągły n‑2 zamknij nawias okrągły minus 3. Linia 7. w przeciwnym razie wykonaj dwukropek. Linia 8. zwróć funkcja otwórz nawias okrągły n‑1 zamknij nawias okrągły mod 9.

Zapisaliśmy za pomocą pseudokodu funkcję zwracającą n‑ty wyraz ciągu rekurencyjnego.

Ćwiczenie 3

Dla powyższego pseudokodu obliczmy zwracane wartości dla n z zakresu od 0 do 7.

funkcja(0) = 122
funkcja(1) = 122
funkcja(2)=funkcja(0)3 = 122  3 = 119
funkcja(3) = funkcja(2) mod 9 = 119 mod 9 = 2
funkcja(4) = funkcja(2)  3 = 119  3 = 116
funkcja(5) = funkcja(4) mod 9 = 116 mod 9 = 8
funkcja(6) = funkcja(4)  3 = 116  3 = 113
funkcja(7) = funkcja(6) mod 9 = 113 mod 9 = 5

Funkcja wywołuje samą siebie we wszystkich przypadkach poza tymi, kiedy n = 0 lub n = 1. Na przykład funkcja(5) wywołuje funkcję funkcja(4). Nie musimy jednak ponownie wyznaczać wartości tej funkcji, ponieważ obliczyliśmy ją w poprzednim kroku.

Ciąg rekurencyjny

Przeanalizujmy przedstawioną za pomocą pseudokodu funkcję ciąg(x, y) przyjmującą parametry x i y typu całkowitego, której wywołanie spowoduje wypisanie ciągu liczb całkowitych:

Linia 1. funkcja ciąg otwórz nawias okrągły x przecinek y zamknij nawias okrągły. Linia 2. jeżeli y zamknij nawias ostrokątny 0 wykonaj dwukropek. Linia 3. ciąg otwórz nawias okrągły 2 asterysk x przecinek y minus 1 zamknij nawias okrągły. Linia 4. ciąg otwórz nawias okrągły 3 asterysk x przecinek y minus 2 zamknij nawias okrągły. Linia 5. wypisz x minus y.
Ćwiczenie 4

Wypiszmy wszystkie wywołania rekurencyjne funkcji ciąg(2, 4).

Do wykonania tego zadania pomocne okaże się drzewo wywołań rekurencyjnych, w którym umieścimy wszystkie wywołania funkcji ciąg(2, 4).

RnSB7aDOaIbrb
Źródło: Contentplus.pl Sp. z o.o., licencja: CC BY-SA 3.0.

W drzewie zostały przedstawione wywołania tylko tych funkcji, których wartość drugiego przyjmowanego argumentu, czyli y, jest większa od 0. Z tego względu wykonania niektórych funkcji powodują wywołanie tylko jednej rekurencyjnej funkcji. Lewa strzałka każdej z funkcji prowadzi do wywołania funkcji ciąg(2*x, y‑1), natomiast prawa prowadzi do ciąg(3*x, y‑2).

Ćwiczenie 5

Podajmy teraz wynik działania funkcji ciąg(2, 4) i uzupełnijmy wygenerowany ciąg rekurencyjny:

15   6

Ponownie skorzystamy z drzewa wywołań rekurencyjnych. Wiemy, że nasz ciąg to uzyskane wartości działań x - y. Jednak w jakiej kolejności wypisywane są te wartości? Spójrzmy ponownie na zapisaną za pomocą pseudokodu funkcję ciąg(x, y). Najpierw zostanie wywołana rekurencyjnie funkcja ciąg(2*x, y‑1), czyli lewa skierowana krawędź, następnie ciąg(3*x, y‑2), czyli prawa krawędź, a na końcu wypisana zostanie wartość x - y.

A zatem początek wygenerowanego ciągu rekurencyjnego zgadza się z naszymi wnioskami. W pierwszej kolejności wykonywane jest najniżej położone, lewe poddrzewo, zatem wywołana zostanie funkcja ciąg(16, 1).

16  1 = 15

Następnie miałoby zostać wykonane prawe poddrzewo, jednak takie nie istnieje, przechodzimy więc do wyższego poziomu, czyli ciąg(8, 2). Stosując powyższe obserwacje, uzyskamy następujący ciąg:

15   6   11   1   11   4   2

Słownik

przypadek podstawowy
przypadek podstawowy

przypadek, dla którego funkcja rekurencyjna nie wywołuje samej siebie (warunek zakończenia), zwraca za to konkretną, wyliczoną wartość; jest to pewien założony stan początkowy

silnia
silnia

n! – iloczyn kolejnych liczb naturalnych, mniejszych lub równych n