Prezentace se nahrává, počkejte prosím

Prezentace se nahrává, počkejte prosím

Rekurze.

Podobné prezentace


Prezentace na téma: "Rekurze."— Transkript prezentace:

1 Rekurze

2 Rekurze volání podprogramu opětovně v jeho těle Druhy rekurze
v době, kdy předchozí volání ještě nebylo ukončeno Druhy rekurze přímá rekurze nepřímá rekurze

3 Přímá rekurze podprogram volá sám sebe void A(…) { A(); }

4 Nepřímá rekurze aktivují se vzájemně dva podprogramy void A(…) { B();
} void B(…) A();

5 pravidla tvorby rekurzivní funkce
musí být definována podmínka pro ukončení rekurze v algoritmu se musí ověřit, zda nenastala koncová situace v každém kroku musí dojít ke zjednodušení problému

6 Napište rekurzivní funkci pro výpočet faktoriálu
Příklad 1 Napište rekurzivní funkci pro výpočet faktoriálu long fakt(int n) { if (n<=1) return 1; else return n*fakt(n-1); }

7 Jak se rekurze volá? int main() { fakt(2); } fakt(2) return 2*fakt(1)

8 V registru procesoru AX se předává návratová hodnota
long fakt(int n) { long x; 1: if (n<=1) 2: return 1; 3: else { 4: x=fakt(n-1); 5: x = n*x; 6: return x; } int main() {long a; 10: a = fakt(3); 11: cout << a; } AX: 2584 a 4589 Zásobník n 3

9 V registru procesoru AX se předává návratová hodnota
long fakt(int n) { long x; 1: if (n<=1) 2: return 1; 3: else { 4: x=fakt(n-1); 5: x = n*x; 6: return x; } int main() {long a; 10: a = fakt(3); 11: cout << a; } AX: 2584 a 4589 Zásobník x 11 n 3

10 V registru procesoru AX se předává návratová hodnota
long fakt(int n) { long x; 1: if (n<=1) 2: return 1; 3: else { 4: x=fakt(n-1); 5: x = n*x; 6: return x; } int main() {long a; 10: a = fakt(3); 11: cout << a; } AX: 2584 a 4589 Zásobník x 11 n 3

11 V registru procesoru AX se předává návratová hodnota
long fakt(int n) { long x; 1: if (n<=1) 2: return 1; 3: else { 4: x=fakt(n-1); 5: x = n*x; 6: return x; } int main() {long a; 10: a = fakt(3); 11: cout << a; } AX: 2584 a 4589 Zásobník n 2 x 11 n 3

12 V registru procesoru AX se předává návratová hodnota
long fakt(int n) { long x; 1: if (n<=1) 2: return 1; 3: else { 4: x=fakt(n-1); 5: x = n*x; 6: return x; } int main() {long a; 10: a = fakt(3); 11: cout << a; } AX: 2584 a 4589 Zásobník 5 n 2 x 11 n 3

13 V registru procesoru AX se předává návratová hodnota
long fakt(int n) { long x; 1: if (n<=1) 2: return 1; 3: else { 4: x=fakt(n-1); 5: x = n*x; 6: return x; } int main() {long a; 10: a = fakt(3); 11: cout << a; } AX: 2584 a 4589 Zásobník x 5 n 2 x 11 n 3

14 V registru procesoru AX se předává návratová hodnota
long fakt(int n) { long x; 1: if (n<=1) 2: return 1; 3: else { 4: x=fakt(n-1); 5: x = n*x; 6: return x; } int main() {long a; 10: a = fakt(3); 11: cout << a; } AX: 2584 a 4589 Zásobník x 5 n 2 x 11 n 3

15 V registru procesoru AX se předává návratová hodnota
long fakt(int n) { long x; 1: if (n<=1) 2: return 1; 3: else { 4: x=fakt(n-1); 5: x = n*x; 6: return x; } int main() {long a; 10: a = fakt(3); 11: cout << a; } AX: 2584 a 4589 Zásobník n 1 x 5 n 2 x 11 n 3

16 V registru procesoru AX se předává návratová hodnota
long fakt(int n) { long x; 1: if (n<=1) 2: return 1; 3: else { 4: x=fakt(n-1); 5: x = n*x; 6: return x; } int main() {long a; 10: a = fakt(3); 11: cout << a; } AX: 2584 a 4589 Zásobník x 5 n 1 x 5 n 2 x 11 n 3

17 V registru procesoru AX se předává návratová hodnota
long fakt(int n) { long x; 1: if (n<=1) 2: return 1; 3: else { 4: x=fakt(n-1); 5: x = n*x; 6: return x; } int main() {long a; 10: a = fakt(3); 11: cout << a; } AX: 2584 a 4589 Zásobník x 5 n 1 x 5 n 2 x 11 n 3

18 V registru procesoru AX se předává návratová hodnota
long fakt(int n) { long x; 1: if (n<=1) 2: return 1; 3: else { 4: x=fakt(n-1); 5: x = n*x; 6: return x; } int main() {long a; 10: a = fakt(3); 11: cout << a; } AX: 1 a 4589 Zásobník 5 n 1 x 5 n 2 x 11 n 3

19 V registru procesoru AX se předává návratová hodnota
long fakt(int n) { long x; 1: if (n<=1) 2: return 1; 3: else { 4: x=fakt(n-1); 5: x = n*x; 6: return x; } int main() {long a; 10: a = fakt(3); 11: cout << a; } AX: 1 a 4589 Zásobník n 1 x 1 5 n 2 x 11 n 3

20 V registru procesoru AX se předává návratová hodnota
long fakt(int n) { long x; 1: if (n<=1) 2: return 1; 3: else { 4: x=fakt(n-1); 5: x = n*x; 6: return x; } int main() {long a; 10: a = fakt(3); 11: cout << a; } AX: 1 a 4589 Zásobník x 1 5 n 2 x 11 n 3

21 V registru procesoru AX se předává návratová hodnota
long fakt(int n) { long x; 1: if (n<=1) 2: return 1; 3: else { 4: x=fakt(n-1); 5: x = n*x; 6: return x; } int main() {long a; 10: a = fakt(3); 11: cout << a; } AX: 2584 a 4589 Zásobník x 2 5 n 2 x 11 n 3

22 V registru procesoru AX se předává návratová hodnota
long fakt(int n) { long x; 1: if (n<=1) 2: return 1; 3: else { 4: x=fakt(n-1); 5: x = n*x; 6: return x; } int main() {long a; 10: a = fakt(3); 11: cout << a; } AX: 2 a 4589 Zásobník 5 n 2 x 11 n 3

23 V registru procesoru AX se předává návratová hodnota
long fakt(int n) { long x; 1: if (n<=1) 2: return 1; 3: else { 4: x=fakt(n-1); 5: x = n*x; 6: return x; } int main() {long a; 10: a = fakt(3); 11: cout << a; } AX: 2 a 4589 Zásobník n 2 x 2 11 n 3

24 V registru procesoru AX se předává návratová hodnota
long fakt(int n) { long x; 1: if (n<=1) 2: return 1; 3: else { 4: x=fakt(n-1); 5: x = n*x; 6: return x; } int main() {long a; 10: a = fakt(3); 11: cout << a; } AX: 2 a 4589 Zásobník x 2 11 n 3

25 V registru procesoru AX se předává návratová hodnota
long fakt(int n) { long x; 1: if (n<=1) 2: return 1; 3: else { 4: x=fakt(n-1); 5: x = n*x; 6: return x; } int main() {long a; 10: a = fakt(3); 11: cout << a; } AX: 2 a 4589 Zásobník x 6 11 n 3

26 V registru procesoru AX se předává návratová hodnota
long fakt(int n) { long x; 1: if (n<=1) 2: return 1; 3: else { 4: x=fakt(n-1); 5: x = n*x; 6: return x; } int main() {long a; 10: a = fakt(3); 11: cout << a; } AX: 6 a 4589 Zásobník 11 n 3

27 V registru procesoru AX se předává návratová hodnota
long fakt(int n) { long x; 1: if (n<=1) 2: return 1; 3: else { 4: x=fakt(n-1); 5: x = n*x; 6: return x; } int main() {long a; 10: a = fakt(3); 11: cout << a; } AX: 6 a 6 Zásobník n 3

28 V registru procesoru AX se předává návratová hodnota
long fakt(int n) { long x; 1: if (n<=1) 2: return 1; 3: else { 4: x=fakt(n-1); 5: x = n*x; 6: return x; } int main() {long a; 10: a = fakt(3); 11: cout << a; } AX: 6 a 6 Zásobník

29 Úloha 1 Napište rekurzivní funkci pro výpočet Fibbonaciho posloupnosti
F(n) = F(n-1) + F(n-2)

30 rekurze, je-li příliš „hluboká“, způsobí růst velikosti zásobníku
v některých případech je možné ji nahradit pouhým cyklem jindy se musí simulovat zásobník long fakt(int n) { long faktorial = 1; for(i=2;i<=n;i=i+1) faktorial = faktorial*i; return faktorial; }

31 Úloha 2 Je dána celá částka v Kč. Máme k dispozici mince v hodnotách 20 Kč, 10 Kč, 5 Kč, 2Kč, 1 Kč. Napište rekurzivní proceduru, která vytiskne na obrazovku složení částky z co nejmenšího počtu mincí (vytiskne seznam mincí). Domácí úloha: Odstraňte rekurzi (přepište proceduru pomocí cyklu).

32 Hanojské věže máme 3 tyče (1, 2, 3)
na první tyči je věž z n disků naskládaných na sebe, spodní disk má největší průměr úkol: přemístit věž z tyče 1 na tyč 2 pomocí třetí tyče 3 přesouváním disků za podmínek: v jediném kroku lze přenést jeden disk z tyče na tyč disk lze odložit pouze na tyč nelze položit disk o větším průměru na disk s menším průměrem.

33

34 odkud = tyč 1 kam = tyč 2 pomocí = tyč 3

35 void Prenes_disk(int odkud, int kam),
triviální úloha přenesení věže o výšce 1, tj. přenesení disku, z tyče na tyč je reprezentována procedurou void Prenes_disk(int odkud, int kam), která v našem programu vypíše informaci o přesunu disku, např.: 1 -> 2 úvaha chci-li přesunout věž např. o výšce 3 disky z tyče 1 na tyč 2 pomocí tyče 3, musím nejprve přesunout věž o výšce 2 (počítáno od shora) na tyč 3 pomocí 2, pak přesunout spodní největší disk z tyče 1 na tyč 2 a nakonec přesunout věž o výšce 2 z tyče 3 na tyč 2 pomocí tyče 1

36 void prenes_vez(int vyska, int odkud, int kam, int pomoci)
{ if (vyska == 1) prenes_disk(odkud,kam); else prenes_vez(vyska-1, odkud, pomoci, kam); prenes_disk(odkud,kam); prenes_vez(vyska-1,pomoci,kam,odkud); }

37 Jaká je složitost algoritmu?
přesunutí věže o n discích se skládá z přesunutí věže o (n-1) discích, přesunutí disku a přesunutí věže zpět o (n-1) discích počet kroků algoritmu (počet přesunutí disků) je dán rekurentním vztahem: F(n) = F(n-1) F(n-1) = 2F(n-1)+1, přičemž F(1) = 1

38 tj. počet přesunů disku u věže výšky n je roven 2n - 1
řešením rovnice je vztah F(n) = 2n - 1 tj. počet přesunů disku u věže výšky n je roven 2n - 1 složitost algoritmu je tedy O(2n) exponenciální

39 Aplikace rekurze Prohledávání s návratem (Backtracking)
používá se pro hledání všech řešení daného problému princip: řešení hledám po krocích, pokud je řešení nalezeno nebo nelze úlohu dále řešit, vrátím se o krok zpět úlohy: hledání všech cest v bludišti problém rozmístění 8 dam na šachovnici

40 Problém 8 dam na šachovnici
úkol: umístit 8 dam na šachovnici 8x8 polí, aby se vzájemně neohrožovaly princip: umístím dámu na první řádek na první sloupec, další dámu na druhý řádek na třetí sloupec atd., pokud nemohu další dámu umístit, provedu návrat na předchozí řádek a dámu posunu

41 Problém 8 dam demonstrace na 4 dámách na šachovnici 4x4

42 Problém 8 dam

43 Problém 8 dam další dámu nemohu umístit, provedu návrat

44 Problém 8 dam

45 Problém 8 dam

46 Problém 8 dam další dámu nemohu umístit, provedu návrat

47 Problém 8 dam

48 Problém 8 dam

49 Problém 8 dam

50 Problém 8 dam

51 Problém 8 dam

52 Problém 8 dam

53 Rozděl a panuj (Divide and Conquer)
používá se pro zjednodušení řešení složitého problému princip: rozdělím prostor řešení na dva menší (pokud možno stejně velké) podprostory vyřeším problém na každém podprostoru samostatně (stejnou technikou) spojím obě řešení úlohy: Hanojské věže řazení: QuickSort

54 Hledání cest v bludišti

55 algoritmus s návratem (rekurzivní)
je-li to možné, v každé místnosti zkusím „jít na všechny“ světové strany do další místnosti pokud jsem našel východ, vypíši cestu a vrátím se o krok zpět vracím se o krok zpět, nemohu-li postoupit do další mísnosti (jsem v slepé uličče)

56 Jak bude principiálně algoritmus vypadat? Napišme jej v pseudokódu.
Připomeňme si pravidla tvorby rekurzivní procedury: podmínka ukončení rekurze nalezení východu nebo slepá ulička zjednodušení problému v dalším kroku postoupil jsem do další místnosti (nalezená cesta je o 1 krok delší)

57 jdi_do_mistnosti(kam)
{ if (jsem_venku) { tiskni_cestu(); return; } else if (mohu_na_sever) jdi_do_mistnosti(sever); if (mohu_na_jih) jdi_do_mistnosti(jih); if (mohu_na_vychod) jdi_do_mistnosti(vychod); if (mohu_na_zapad) jdi_do_mistnosti(zapad); }

58 Data + Algorithms = Programs
Donald Knuth Data + Algorithms = Programs Rozmyslíme si datové struktury a algoritmy nad nimi !

59 Co lze řešit rekurzí (prohledávání s návratem)
Kostka domina je tvořena dvěma poli. Každé z nich může být prázdné nebo může obsahovat jistý počet teček od 1 do 6. Kostky se skládají do řady tak, že vedle sebe stojící kostky musí sousedit stejnými poli; za kostkou s prázdným polem nelze dát další kostku. Vstupem vašeho programu bude soubor se seznamem kostek domina, které máte k dispozici (na každém řádku bude dvojice čísel oddělená mezerou, představující počet teček). V seznamu se může opakovat i více stejných kostek. Zjistěte jakou nejdelší řadu lze z těchto kostek sestavit. Vytiskněte tuto řadu a její délku měřenou počtem kostek. Stačí jedno řešení.


Stáhnout ppt "Rekurze."

Podobné prezentace


Reklamy Google