- - Jak vytvořit rekurzi v Javě - rekurzivní funkce

Jak vytvořit rekurzi v Javě - rekurzivní funkce

Rekurze je proces definování něčeho z hlediskasám. Pokud jde o programování v jazyce Java, rekurze je atribut, který umožňuje metodě volat sama sebe. Metoda, která sama volá, je rekurzivní a Java podporuje rekurzi.

Zpočátku se to může zdát jako nekonečná smyčka,a zdá se, že naše metoda nikdy nedokončí. To může být pravda v některých případech, ale v praxi můžeme zkontrolovat, zda je určitá podmínka pravdivá, a v takovém případě opustit (vrátit se) naši metodu. Případ, ve kterém skončíme naši rekurzi, se nazývá a základní případ. Navíc, stejně jako ve smyčce, musíme změnit nějakou hodnotu a postupně postupovat blíže k našemu základnímu případu.

Každá rekurze by měla mít následující vlastnosti:

  1. Jednoduchý základní případ, pro který máme řešení a návratovou hodnotu.
  2. Způsob, jak přiblížit náš problém základnímu případu. tj. způsob, jak vyříznout část problému a získat poněkud jednodušší problém.
  3. Rekurzivní volání, které předává jednodušší problém zpět do metody.

Výhody

Hlavní rekurzivní metody jsou, že mohou býtslouží k vytvoření jasnějších a jednodušších verzí několika algoritmů, než mohou jejich iterativní příbuzní. Například třídicí algoritmus QuickSort je docela obtížné implementovat iteračním způsobem.

Nevýhody

Rekurzivní verze mnoha rutin mohou provádětbit pomaleji než iterativní ekvivalent kvůli přidané režii dalších volání funkcí. Mnoho rekurzivních volání metody může způsobit přetečení zásobníku. Protože úložiště parametrů a lokálních proměnných je možné, že by zásobník mohl být vyčerpán. Pokud k tomu dojde, způsobí běhový systém java výjimku. Pravděpodobně se však nebudete muset obávat, pokud rekurzivní rutina není divoká.

Například:

int myFactorial(int integer) {
if( integer == 1) {
return 1;
}
else {
return(integer*(myFactorial(integer-1);
}
}

Rekurze ocasu je definována jako nastávající, kdyžrekurzivní volání je na konci rekurzivní instrukce. To není případ mého faktoriálního řešení výše. Je užitečné si všimnout, kdy jeden algoritmus používá rekurzi ocasu, protože v takovém případě lze algoritmus obvykle přepsat, aby místo něj používal iteraci. Ve skutečnosti kompilátor (nebo alespoň by měl) převést rekurzivní program na iterativní. To eliminuje potenciální problém přetečení zásobníku.

To není případ rekurze hlavy nebo kdyfunkce se rekurzivně volá na různých místech, jako je řešení v Hanoji. Samozřejmě i v těchto případech bychom mohli rekurzi odstranit také pomocí našeho vlastního zásobníku a v podstatě simulováním, jak by rekurze fungovala.

V mém příkladu faktoriálu nad kompilátorembude muset zavést rekurzivní funkci před provedením násobení, protože musí vyřešit (návratovou) hodnotu funkce, než může dokončit násobení. Pořadí provedení tedy bude „hlavová“ rekurze, tj. K rekurzi dochází před jinými operacemi.

Abychom to převedli na rekurzi ocasu, musíme se dostatvšechny multiplikace byly dokončeny a vyřešeny před rekurzivním vyvoláním funkce. Musíme vynutit pořadí operací, abychom nečekali na násobení, než se vrátíme. Pokud tak učiníme, může být rám zásobníku uvolněn.

Dříve jste viděli náš program Java pro výpočet faktoriálu celého čísla.

Správný způsob, jak udělat ocas rekurzivní faktoriál, je tento:

int factorial(int number) {
if(number == 0) {
return 1;
}
factorial_i(number, 1);
}
int factorial_i(int currentNumber, int sum) {
if(currentNumber == 1) {
return sum;
} else {
return factorial_i(currentNumber - 1, sum*currentNumber);
}
}

Všimněte si, že v hovoru zpětfactorial_i (currentNumber - 1, součet * currentNumber); oba parametry jsou okamžitě rozlišitelné. Můžeme vypočítat, co je každý parametr, bez čekání na návrat rekurzivního volání funkce. To neplatí pro předchozí verzi faktoriálu. Toto zjednodušení umožňuje kompilátoru minimalizovat použití zásobníku, jak je vysvětleno výše.

Můžete také vzít číslo od uživatele jako argument příkazového řádku.

Program rekurze Java

class Factorial{
int fact(int n){
int result;
if ( n ==1)
return 1;
result = fact (n-1) * n;
return result;
}
}
class Recursion{
public static void main (String args[]){
Factorial f =new Factorial();
System.out.println("Factorial of 3 is " + f.fact(3));
System.out.println("Factorial of 4 is " + f.fact(4));
System.out.println("Factorial of 5 is " + f.fact(5));
}
}

Výstup

rekurze

Vysvětlení kódu a výstupu Java

Pokud nejste obeznámeni s rekurzivními metodami, pak operace skutečnost() může vypadat trochu matoucí. Takto to funguje. Když skutečnost() je volána s argumentem 1, funkce vrací 1; jinak vrátí produkt skutečnost (n-1) * n. vyhodnotit tento výraz, skutečnost() se volá n-1. Tento proces se opakuje do n rovná se 1 a volání metody se vrací.

Chcete-li lépe pochopit, jak skutečnost() metoda funguje, pojďme krátkým příkladem. Když vypočítáte faktoriál 3, první volání na skutečnost() způsobí druhé volání s argumentem 2. Toto vyvolání vyvolá skutečnost() být volán potřetí s argumentem 2. Toto volání vrátí 1, které se poté nazývá potřetí s argumentem 1. Toto volání vrátí 1, které se pak vynásobí 2 (hodnota n ve druhém vyvolání). Tento výsledek (který je 2) je poté vrácen původnímu vyvolání skutečnost() a vynásobte 3 (původní hodnota n). Tím získáte odpověď 6. Možná bude zajímavé vložit println () prohlášení do skutečnost() která ukáže, na jaké úrovni je každý hovor a jaké jsou průběžné odpovědi.

Když metoda volá sama sebe, nové lokální proměnnéa parametry jsou přiděleny úložiště na zásobníku a kód metody je spuštěn s těmito novými proměnnými od začátku. Rekurzivní volání nevytvoří novou kopii metody. Nové jsou pouze argumenty. Po návratu každého rekurzivního volání jsou ze zásobníku odstraněny staré lokální proměnné a parametry a provádění pokračuje v bodě volání uvnitř metody.

Dále se naučíme, jak se vypořádat Pole v Javě.

Podívejte se na další užitečné návody a definitivní pokyny pro programování Java zde.

Komentáře