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

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

Úvod do programování 10. hodina RNDr. Jan Lánský, Ph.D. Katedra informatiky a matematiky Fakulta ekonomických studií Vysoká škola finanční a správní 2015.

Podobné prezentace


Prezentace na téma: "Úvod do programování 10. hodina RNDr. Jan Lánský, Ph.D. Katedra informatiky a matematiky Fakulta ekonomických studií Vysoká škola finanční a správní 2015."— Transkript prezentace:

1 Úvod do programování 10. hodina RNDr. Jan Lánský, Ph.D. Katedra informatiky a matematiky Fakulta ekonomických studií Vysoká škola finanční a správní 2015

2 Jan LánskýÚvod do programování 10. hodina2 Umíme z minulé hodiny Syntax Dvojrozměrné pole Pole polí String.Split() Algoritmy Násobení řádku matice konstantou Prohození dvou řádků matice Součet matic Součin matic ASCII Art

3 Jan LánskýÚvod do programování 10. hodina3 Cíle hodiny Rekurze Faktoriál Přetečení, nekonečná rekurze Převod z desítkové do dvojkové soustavy Vztah rekurze a cyklu Fibonacciho čísla Verze s dynamickým programováním Binární vyhledávání Hanojské věže Kochova vločka

4 Jan LánskýÚvod do programování 10. hodina4 Rekurze: Motivace Volání funkce sama sebou jednotlivá volání jsou nazývána zanoření Kratší a přehlednější zdrojové kódy než v případě zápisu bez pomocí rekurze Vystihnutí hlavní myšlenky algoritmu Oproti zápisu bez pomocí rekurze pomalejší běh programu (desítky procent) Při špatném použití i zhoršení časové složitosti řádově

5 Jan LánskýÚvod do programování 10. hodina5 Pravidla použití rekurze Problém lze rozdělit na menší podproblémy, které vyřeší téže rekurzivní funkce nebo převést problém na menší podproblém Parametr(y) rekurzivní funkce se musí v každém zanoření přibližovat testované hodnotě v ukončovací podmínce Rekurze musí být ukončena podmínkou testující parametr(y) rekurzivní funkce Nepoužívat rekurzi pro kritické systémy (elektrárny, letadla)

6 Jan LánskýÚvod do programování 10. hodina6 Rekurze: faktoriál Nerekurzivní řešení: V cyklu násobíme 1 až n Faktoriál n! = 1*2*…*(n-1)*n Ukončení rekurze Rekurzivní volání funkce sama sebe se sníženou hodnotou parametru. n! = n * (n-1)! Zanoření funkce

7 Jan LánskýÚvod do programování 10. hodina7 Faktoriál: formálně Faktoriál n je součin čísel od 1 do čísla n n! = 1 * 2 * 3 * … * (n-2) * (n-1) * n Faktoriál n-1 je součin čísel od 1 do čísla n - 1 (n-1)! = 1 * 2 * 3 * … * (n-2) * (n-1) Faktoriál n vyjádříme pomocí faktoriálu n-1 n! = (n-1)! * n pro n > 1 n! = 1 pro n = 1 a pro n = 0 Tento zápis je rekurzivní

8 Jan LánskýÚvod do programování 10. hodina8 Rekurze: ladění Breakpoint Světlý podklad značí, že tato funkce je vykonávána Funkce je zanořena, breakpoint byl aktivován opakovaně

9 Jan LánskýÚvod do programování 10. hodina9 Rekurze: Call stack Funkce main Aktuálně se volá faktoriál s hodnotou parametru 4 Kliknutím na řádek aktivujeme libovolnou funkci a můžeme prohlížet její proměnné Zásobník volání funkcí

10 Jan LánskýÚvod do programování 10. hodina10 Faktoriál s výpisy Na začátku funkce napíšeme s jakými parametry je volána Na konci funkce napíšeme, jaká je její výsledná hodnota Aby šel provést závěrečný výpis, museli jsem zavést proměnnou na výsledek

11 Jan LánskýÚvod do programování 10. hodina11 Faktoriál s výpisy Postupně jsme se zanořovali od 8 do 1 Pro 1 se ukončí rekurze Postupně jsme se vynořovali od 1 do 8 Faktoriál pomocí cyklu počíta obdobně jako vynořování z rekurze

12 Jan LánskýÚvod do programování 10. hodina12 Součet čísel 1 až n Obdoba faktoriálu Faktoriál je součin čísel od 1 do n. Nemuseli jsme nic počítat Sn = n*(n - 1)/2 Faktoriál roste velmi rychle, došlo by k přetečení datového typu. Proto ukazujeme součet Kolik je 1+2+ …+ 10000 ?

13 Jan LánskýÚvod do programování 10. hodina13 Přetečení zásobníku volání Došla paměť, přetečení zásobníku

14 Jan LánskýÚvod do programování 10. hodina14 Přetečení zásobníku volání Pokud voláme rekurzivní funkci je nám povolen jen omezený počet zanoření (dle velikosti zásobníku volání) V případě SoucetOd1DoN to bylo 1446 Pro rozumné použití rekurze dostatečně Nejčastěji dojde paměť při nekonečné rekurzi (chybí ukončující podmínka rekurze)

15 Jan LánskýÚvod do programování 10. hodina15 Konečnost rekurze Rejstřík Cyklus nekonečný Viz Nekonečný cyklus Nekonečný cyklus viz Cyklus nekonečný Rekurzivní funkce musí být vždy zakončena podmínkou pro testování hodnoty parametru funkce Parametr funkce se musí v jednotlivých voláních blížit testované hodnotě Faktorial (n) = n * faktorial (n-1) Faktorial (1) = 1 Nepřímá rekurze Občas se zapomene ukončit, pak vznikne nekonečná rekurze

16 Jan LánskýÚvod do programování 10. hodina16 Převod z desítkové do dvojkové soustavy (little endian) Little endian: Postupně vypisujeme zbytky po dělení číslem dvě. Big endian: Obtížné, museli bychom mít pomocné pole Little endian: Postupně vypisujeme zbytky po dělení číslem dvě. Big endián: Stačí prohodit výpis a rekurzivní volání

17 Jan LánskýÚvod do programování 10. hodina17 Převod cyklu na rekurzi Nepoužívat: Uvádíme jen pro ilustraci. Cyklus se vyhodnotí rychleji Voláme rekurzivní funkci s novou hodnotu x Konec rekurze při nesplnění podmínky Místo cyklu vložíme volání rekurzivní funkce

18 Jan LánskýÚvod do programování 10. hodina18 Náhrada rekurze Rekurze je silnější prostředek než cyklus náhradu nelze provést automaticky Převod rekurze na cyklus (cykly) Podmínka ukončující rekurzi odpovídá podmínce cyklu Problematický vyšší počet rekurzivních volání (stromová rekurze) Velmi často je nutno použít datovou strukturu zásobník (bude probírána později) Odstranění rekurze použitím jiného algoritmu bude za chvíli Fibonacci

19 Jan LánskýÚvod do programování 10. hodina19 Fibonacciho čísla F(0) = 0 F(1) = 1 F(n) = F(n-1) + F(n-2) 0, 1, 1, 2, 3, 5, 8, 13, 21, 34, 55, 89, … Zlatý řez lim n  oo F(n) / F(n-1) = (1+  5) / 2 = 1.618 Vyskytuje se často v přírodě (listy, ulita) Řádu 2 Stromová rekurze: Rekurzivní volání je dvakrát Odstrašující příklad na rekurzi

20 Jan LánskýÚvod do programování 10. hodina20 Fibonacciho čísla F(0) = 0 F(1) = 1 F(n) = F(n-1) + F(n-2) Fibonacci(20); Fibonacci(30); Fibonacci(50); Proč je tak pomalé ? Stromová rekurze Časová složitost O(2 N )

21 Jan LánskýÚvod do programování 10. hodina21 Fibonacciho čísla 5 4 3 2321 101021 1 0 Kolikrát počítáme F(0) 3x F(1) 5x F(2) 3x F(3) 2x F(4) 1x F(5) 1x Opakovaně počítáme ty samé hodnoty. Exponenciální časová složitost

22 Jan LánskýÚvod do programování 10. hodina22 Fibonacciho čísla lineárně Technika „Dynamické programování“: Rozklad problému na podproblémy a jejich řešení je uloženo pro další použití Postupně počítáme F(0), F(1), F(2) až F(n). Stačí si nám pamatovat dva poslední členy posloupnosti F(n-1) a F(n-2) Časová složitost O(N)

23 Jan LánskýÚvod do programování 10. hodina23 Fibonacciho čísla lineárně F(0)F(1)F(2)F(3)F(4)F(5)F(6)F(7)F(8)F(9) 01F(0) F(1) F(2) F(3) F(4) F(5) F(6) F(7) F(8) 0112358132134 Př: červená barva kružnice F(1) a F(2) Červená barva pole F(3) = F(1) + F(2)

24 Jan LánskýÚvod do programování 10. hodina24 Binární vyhledávání Hledání prvku v setříděném poli. V 5. přednášce byla probrána nerekurzivní verze Rozpůlíme pole na dvě poloviny, podle hodnoty dělícího prvku se rozhodneme, ve které polovině by se měl prvek nacházet Časová složitost O(log(N)) Rekurzivní verze má také O(log(N))

25 Jan LánskýÚvod do programování 10. hodina25 Binární vyhledávání Pro rekurzivní verzi potřebujeme znát jakou část pole prohledáváme (začátek, konec) Prvek nenalezen, konec rekurze Prvek nalezen, konec rekurze Rekurzivně prohledáme levou nebo pravou část pole – dle hodnoty středového prvku Pole setříděné vzestupně Lineární rekurze, nikdy se neprohledá levá i pravá část najednou Volání z nerekurzivní funkce: častý trik

26 Jan LánskýÚvod do programování 10. hodina26 Binární vyhledávání 5 45 45679 0112345679 049 Hledáme hodnotu 5 v poli p BVNajdi (p, 6, 6, 5) stred = 6, p[stred] == x BVNajdi (p, 5, 6, 5) stred = 5, p[stred] < x BVNajdi (p, 5, 9, 5) stred = 7, p[stred] > x BVNajdi (p, 0, 9, 5) stred = 4, p[stred] < x

27 Jan LánskýÚvod do programování 10. hodina27 Hanojské věže https://www.mathsisfun.com/games/towerofhanoi.html Přemístit všechny disky po z věže 1 do na věž 3 Větší disk nesmí být nikdy umístěn na menší disk V každém tahu lze přemísťovat jen jeden nejvrchnější disk Édouard Lucas, 1883 Počet tahů k vyřešení 2 n - 1, kde n > 1 je počet disků 123456123456

28 Jan LánskýÚvod do programování 10. hodina28 Hanojské věže Rozšíření funkce o pomocné proměnné: z – původní věž, kam – cílová věž, prez – pomocná věž jako odkladiště 1) Přemístíme n-1 disků z původní věže na pomocnou věž s využitím cílové věže jako odkladiště 3) Přesuneme n-1 disků z pomocné věže na cílovou věž s využitím původní věže jako odkladiště 2) Přesun největší disk

29 Jan LánskýÚvod do programování 10. hodina29 Hanojské věže pro n = 4 Vyzkoušejme tento postup v online hře Největší disk 4 Nejmenší disk 1

30 Jan LánskýÚvod do programování 10. hodina30 Kochova vločka Začínáme s trojúhelníkem V každém zanoření z každé hrany odstraníme prostřední třetinu a nahradíme ji dvěma hranami rovnostranného trojúhelníku směřujícími z vločky směrem ven Končíme po zvoleném počtu zanoření http://mathworld.wolfram.com/KochSnowflake.html Zanoření 0 až 3. Vločku tvoří křivka, nikoliv plocha Helge von Koch, 1904 Druh fraktálu

31 Jan LánskýÚvod do programování 10. hodina31 Přímá a nepřímá rekurze Přímá – rekurzivní volání v těle funkce Všechny probrané příklady Nepřímá – rekurzivní volání ve vnořené funkci Př.: Fce1 () { fce2(); } Fce2 () { fce1(); } Příklad Rejstřík – nekonečná rekurze Smysluplný příklad bude v LS

32 Jan LánskýÚvod do programování 10. hodina32 Lineární a stromová rekurze Lineární - obvykle jedna větev rekurzivního volání nebo více větví, které se volají s parametrem odpovídajícímu n vydělenému počtem větví. Př.: faktoriál – jedna větev [n-1], Př.: binární vyhledávání – dvě větve [n/2], ale navíc se se vykoná jen jedna Stromová – více větví rekurzivních volání, které se volají s parametrem odpovídajícím původnímu parametru (zmenšenému o konstantou) Př.: Fibonacciho čísla – dvě větve [n-1] a [n-2] Př.: Hanojské věže – dvě větve [n-1]

33 Jan LánskýÚvod do programování 10. hodina33 Časová složitost Rekurze je vždy pomalejší než nerekurzivní řešení (desítky procent) Někdy nerekurzivní řešení může mít i lepší asymptotickou složitost (Fibonacci) Lineární rekurze – obvykle převod na cyklus – O(N), případně O(log(N)) Stromová rekurze – hrozí O(2 N ), pokud se volá alespoň dvakrát o délce N

34 Jan LánskýÚvod do programování 10. hodina34 Zpětná vazba Objevili jste ve slajdech chyby? Včetně pravopisných Nechápete nějaký slajd? Je příliš obtížný, nesrozumitelný? Máte nějaký nápad na vylepšení? Anonymní formulář Odeslání za pár vteřin http://goo.gl/forms/WxkZqBsZLs


Stáhnout ppt "Úvod do programování 10. hodina RNDr. Jan Lánský, Ph.D. Katedra informatiky a matematiky Fakulta ekonomických studií Vysoká škola finanční a správní 2015."

Podobné prezentace


Reklamy Google