diff --git a/KIV PPA2/Prednaska06.md b/KIV PPA2/Prednaska06.md new file mode 100644 index 0000000..750c0bd --- /dev/null +++ b/KIV PPA2/Prednaska06.md @@ -0,0 +1,120 @@ +# Odstranění rekurze + +**Proč?** +- problémy s hloubkou zanoření (velikost zásobníku je malá) +- neefektivní , protože se při volání metod kopírují hodnoty skutečných parametrů do zásobníku + +### Koncová rekurze + +- kód končí jediným rekurzivním voláním +- nejjednodušší druh rekurze, je snadné přepsat na cyklus + +### Eliminace vlastním zásobníkem + +- použití zásobníku jako seznamu úkolů (například třída `Task`) +- položky v zásobníku budou obsahovat: + - co se má udělat (parametry) + - v jaké čísti úkolu jsme (segment) + - data nutná pro pokračování výpočtu (mezivýsledky) +- pokud je potřeba pro dokončení úkolu rekurze, přidá se do zásobníku nový úkol +- až se dojde k triviálnímu úkolu, data se předají dalšímu úkolu + +**Jak rekurzi odstranit?** +- rozdělíme kód na segmenty mezi rekurzivními voláními +- na začátku do zásobníku vložíme pouze hlavní úkol +- zpracováváme položky zásobníku, dokud není prázdný +- místo rekurzivního volání: + - uložíme stav výpočtu položky na vrcholu zásobníku (stavové proměnné) + - zvýšíme segment na vrcholu zásobníku (jsme o jednu část úkolu dál) + - do zásobníku přidáme nový úkol reprezentující rekurzi + - ukončíme zpracování aktuálního úkolu (smyčka se k němu vrátí později) +- místo vrácení hodnoty: + - uložíme výsledek do proměnné `result` + - odebereme úkol z vrcholu zásobníku +- při pokračování dalším segmentem: + - obnovíme stavové proměnné z položky na vrcholu zásobníku + - výsledek posledního rekurzivního volání se nachází v proměnné `result` +- na konci vrátímě proměnnou `result` + +**Závěr** +- každou rekurzivní funkci je možné přepsat bez použití rekurze + - pracný mechanický postup + - horší přehlednost kódu + - potřeba implementace zásobníku +- přepsání bez rekurze zachovává třídu složitosti (nezajišťuje efektivitu) +- pro nalezení efektivnější implementace mechanický postup neexistuje + +# Fronta + +- abstraktní datová struktura +- podobá se zásobníku +- FIFO - first in, first out + +**Operace** +- přidání prvku na konec +- vybrání prvku na začátku začátku +- odebrání prvku na začátku začátku + +### Implementace spojovým prvkem + +- velmi podobná zásobníku +- kromě odkazu na první prvek uchovává i **odkaz na poslední prvek** + +**Složitost operací** +- všechny $\Theta(1)$ +- vyšší náročnost na paměť + +### Implementace polem + +- velmi podobná zásobníku +- po odebrání vznikají prázdná místa v poli + - je možné je využít pro přidávání +- struktura obsahuje: + - index prvního prvku + - počet obsazených indexů +- při přidávání prvku: + - kontrolujeme, jestli se prvek do pole vejde + - pokud je **místo na začátku**, vložíme prvek na začátek pole + - pokud je **pole plné** zvětšíme pole a zkopírujeme od indexu prvního prvku až do délky pole + - využijeme modula - pomocí něj index "přeteče" na začátek pole + - máme pole o 5 prvcích + - vkládáme na index 5, nicméně 5 % 5 je 0 (začátek pole) + +**Složitost operací** +- vybrání/odebrání prvního prvku $\Theta(1)$ +- přidání prvku na konec: + - většinou $\Theta(1)$ + - při zvětšení pole $\Theta(n)$ + - v průměru $\Theta(1)$ + +# Třídy s typovým parametrem + +- často potřeba kolekce pro různé datové typy +- není vhodné vytvářet samostatné kolekce (třídy) pro různé datové typy + +### Řešení pomocí Object + +- všechny třídy dědí z Object +- vkládání není problém +- při vybrání prvku je potřeba **jej přetypovat** +- případná chyba se objeví až za běhu programu + +**Obalovací třída** +- anglicky wrapper +- poskytuje metody, které provádějí **přetypování na správnou třídu** +- skrývá vnitřní implementaci s `Object` +- je potřeba ji vytvořit pro každý datový typ + +**Generická třída** +- třída s typovým parametrem `class MyStack` + - datový typ `Object` poté nahradíme typem `T` + - bohužel nefunguje všude + - typ `T` pouze přebíráme a vracíme + - vnitřně používáme `Object`, který poté přetypujeme +- typovým parametrem nemůže být primitivní datový typ + - využijeme obalovací třídu (`Integer`, `Double`, ...) + - přetypování (boxing a unboxing) probíhá automaticky, je ale dobré o něm vědět +- někdy je potřeba, aby typový parametr něco uměl + - je možné použít rozhraní + - `class MyStack` + - pokud potřebujeme použít nějakou metodu tohoto rozhraní ve třídě, můžeme `Object` přetypovat na `T` \ No newline at end of file