100 likes | 289 Views
Ackermannova funkce. Ukázka odstranění rekurze Přemysl Tišer. Definice. A(0,n)=n+1 A(m,0)=A(m-1,1) A(m,n)=A(m-1,A(m,n-1)) v ostatních případech. Návrh shora dolů. Zdánlivě jednoduchá rekurzivní definice vede na jednoduchý rekurzivní algoritmus: public static int ackRek(int m, int n) {
E N D
Ackermannova funkce Ukázka odstranění rekurze Přemysl Tišer
Definice • A(0,n)=n+1 • A(m,0)=A(m-1,1) • A(m,n)=A(m-1,A(m,n-1)) v ostatních případech
Návrh shora dolů • Zdánlivě jednoduchá rekurzivní definice vede na jednoduchý rekurzivní algoritmus: public static int ackRek(int m, int n) { if (m==0) return n+1; // programátorská hrůza if (n==0) return ackRek(m-1,1); return ackRek(m-1, ackRek(m, n-1)); }
Problémy s rekurzí • Každé volání funkce téměř vždy znamená další dvě volání • Možnosti počítače se vyčerpají již při nízkých hodnotách m,n • Počet volání roste zhruba jako 4n, což pro n=8 dává 2785999 • Pozn.: Pro A(4,1) program skončil přetečením zásobníku
Odstranění rekurze I • Na začátku funkce definujeme zásobník pro ukládání parametrů • Použijeme jeden cyklus pro vkládání parametrů, druhý pro odebírání parametrů, pro které již byla Ackermannova funkce spočítána • Oba cykly se budou podle potřeby střídat
Odstranění rekurze II • Na vrchol zásobníku vždy uložíme hodnoty m, n, pro které budeme potřebovat provést výpočet • Po zpracování vrcholu zásobníku, parametry na tomto vrcholu odebereme • Jakmile se vrátíme na první vložený záznam, spočítáme výsledek funkce a skončíme
Odstranění rekurze III • Hodnotu n, kterou bude teprve potřeba spočítat, budeme reprezentovat číslem -1, které bude po provedení výpočtu nahrazeno správnou hodnotou
Algoritmus I • Konkrétní řešení lze nalézt v přiloženém kódu • ackRek používá rekurzi • ackermann využívá výše popsaný způsob • Uvedený algoritmus je pouze polotovar, lze vylepšit tak, aby zbytečně neukládal na zásobník parametry m,n, pro které je již Ackermannova funkce spočítána. Takto je ponechá pro větší názornost.
Algoritmus II • Jako zásobník používám z lenosti ;o) dvě pole mZas a nZas, pro ukládání výsledků dvourozměrné pole pomTab. • Použitá literatura: Miroslav Virius: Základy algoritmizace, skriptum ČVUT