///////////////////////////////////////////////////////// faktorial ///////////////////////////////////////////////////////// static int faktorial(int n) { int vysledek; if(n == 1) return 1; vysledek = faktorial(n-1) * n; return vysledek; } postupný směr volání --------------------------------------------> faktorial(5) * faktorial(4) * faktorial(3) * faktorial(2) * faktorial(1) <----------------------------------------------------------- postupný směr výpočtu pro n=5 (5-1) * 5 (4-1) * 4 (3-1) * 3 (2-1) * 2 * 1 5 * ((5-1) * ((4-1) * ((3-1) * (2-1)))) = 5 * ((5-1) * ((4-1) * ((3-1) * 1))) = 5 * ((5-1) * ((4-1) * 2)) = 5 * ((5-1) * 6) = 5 * 24 = 120 ---------------------------------------------------------- static int faktorial(int n) { int vysledek; if (n == 0) return 1; vysledek = faktorial(n - 1) * n; return vysledek; } faktorial(5) * faktorial(4) * faktorial(3) * faktorial(2) * faktorial(1) * faktorial(0) // 5*4*3*2*1*1 - dvě různé jedničky, první je 2-1, druhá přímo návratová hodnota v důsledku splnění podmínky n == 0 ---------------------------------------------------------- ////////////////////////////////////////////////////////// nejvetsi spolecny delitel ////////////////////////////////////////////////////////// static int UrciDelitel(int A, int B) { if (A != B) if (A > B) { return UrciDelitel(A - B, B); } else { return UrciDelitel(A, B - A); } else return A; } pro A=35 B=25 UrciDelitel(35 , 25) UrciDelitel(35 - 25, 25) UrciDelitel(10 , 25 - 10) UrciDelitel(10 , 15 - 10) UrciDelitel(10 - 5, 5) A==B --> výsledek 5 --------------------------------------------------------- static int UrciDelitel(int A, int B) { if (B!=0) if (A > B) { return UrciDelitel(B, A % B); } else { return UrciDelitel(A, B % A); } else return A; } pro A=35 B=25 UrciDelitel(35 , 25) UrciDelitel(25 , 35%25) UrciDelitel(10 , 25%10) UrciDelitel(5 , 10%5) B==0 --> výsledek 5 pro A=25 B=35 UrciDelitel(25 , 35) UrciDelitel(25 , 35%25) UrciDelitel(10 , 25%10) UrciDelitel(5 , 10%5) B==0 --> výsledek 5 --------------------------------------------------------- static int UrciDelitel(int A, int B) { if (B == 0) return A; return UrciDelitel(B, A % B); } pro A=25 B=35 UrciDelitel(25 , 35) !!UrciDelitel(35, 25%35)!! pouze prohodi pro další volání hodnoty A s B UrciDelitel(25 , 35%25) UrciDelitel(10 , 25%10) UrciDelitel(5 , 10%5) B==0 --> výsledek 5 --------------------------------------------------------- ///////////////////////////////////////////////////////// fibonacciho posloupnost ///////////////////////////////////////////////////////// static int fibonaci(int n) { if (n == 0) return 0; else if (n == 1) return 1; else return fibonaci(n - 1) + fibonaci(n - 2); } --------------------------------------------------------- static int fibonaci(int n) { switch (n) { case 0: return 0; break; case 1: return 1; break; default: return fibonaci(n - 1) + fibonaci(n - 2); break; } } ///////////////////////////////////////////////////////// Rekurzi lze uplatnit, pokud programovací jazyk umožňuje volat podprogram opakovaně v době, kdy jeho předchozí volání nebylo ještě ukončeno.To umožňuje způsob práce překladače, který dokáže přeložit volání jakéhokoliv podprogramu již v okamžiku, kdy je dokončen překladnjeho hlavičky. Vlastnosti každé rekurentní konstrukce: •volání sama sebe •volání téhož algoritmu vede k řešení ”menšího” problému •je-li řešen nejjednodušší případ problému, je aktivována podmínka proukončení rekurze a dochází k návratu z konstrukce bez volání sebesama Rozlišujeme dva druhy rekurze: a) přímá rekurze b) nepřímá rekurze (vzájemná rekurze) Přímá rekurze nastává tehdy, když podprogram aktivuje sám sebe. To znamená: v příkazové části podprogramu je příkaz volání podprogramu se stejným identifikátorem. Nepřímá rekurze nastává tehdy, aktivují-li se vzájemně dva podprogramy. Například: funkce A vyvolá funkci B a během jejího provádění se opět volá funkce A. Rekurze dává možnost - definovat nekonečnou množinu objektů konečným příkazem - nekonečný počet výpočtů popsat pomocí konečného rekurzivního programu už jsme se s ní setkali? Určitě nejen v matematice, ale i v denním životě. Příklad: v reklamním obrázku, který obsahuje sám sebe (známá krabička od sirek, kde je vyobrzen orel nesoucí tu stejnou krabičku od sirek s orlem, který nese krabičku... v pohledu kamery na obraz toho, co zobrazuje Rekurze, kde ji použít V programování? a) při definování datové struktury Datová struktura obsahuje prvek, který má stejnou strukturu jako definovaná datová struktura. Definujeme tak nekonečnou datovou strukturu konečným způsobem (například u dynamických struktur). b) při vykonávání programu Obecná úloha se rozkládá na dílčí úlohy, které se vyřeší stejným způsobem. Rozklad zastaví omezující podmínka. * Tato programovací technika se hodí pouze pro určitý omezený okruh úloh, u nichž je rozdělení na menší nezávislé podúlohy stejného charakteru možné a přirozené. * Je-li použitelná, vede zpravidla k poměrně krátkému a efektivnímu programu.