Roztřídění poznámek z PPA2 podle témat
This commit is contained in:
parent
247b469959
commit
b8eb3580e7
|
@ -9,7 +9,7 @@
|
||||||
|
|
||||||
## Rozhraní (interface)
|
## Rozhraní (interface)
|
||||||
|
|
||||||
- popisuje, co nějaká třída umí: hlavičky metod
|
- popisuje, co nějaká třída umí: **hlavičky metod**
|
||||||
- neříká nic o tom, jak jsou metody implementovány
|
- neříká nic o tom, jak jsou metody implementovány
|
||||||
- různé třídy mohou implementovat stejné rozhraní
|
- různé třídy mohou implementovat stejné rozhraní
|
||||||
- jedna třída může implementovat více rozhraní
|
- jedna třída může implementovat více rozhraní
|
||||||
|
@ -41,37 +41,12 @@
|
||||||
- dědit lze vždy jen od **jednoho** předka
|
- dědit lze vždy jen od **jednoho** předka
|
||||||
- referenci na potomka je možné kdykoli přetypovat na referenci na předka
|
- referenci na potomka je možné kdykoli přetypovat na referenci na předka
|
||||||
- přetypovává se **reference**, nikoli instance samotná
|
- přetypovává se **reference**, nikoli instance samotná
|
||||||
- obráceně ne (runtime error) => předek nemusí implementovat vše co potomek
|
- obráceně ne (runtime error), předek nemusí implementovat vše, co potomek
|
||||||
- každou referenci je možné přetypovat na referenci na `Object`
|
- každou referenci je možné přetypovat na `Object`
|
||||||
|
|
||||||
## Polymorfismus
|
## Polymorfismus
|
||||||
|
|
||||||
- instanci potomka lze použít všude kde se očekává předek
|
- instanci potomka lze použít všude kde se očekává předek
|
||||||
- parametr metody
|
- parametr metody
|
||||||
- pole předků
|
- pole předků
|
||||||
- ...
|
- ...
|
||||||
|
|
||||||
# Rekurzivní programy
|
|
||||||
|
|
||||||
- programy, které volají sami sebe
|
|
||||||
- rekurze, musí někdy skončit!
|
|
||||||
|
|
||||||
## Přímá rekurze
|
|
||||||
|
|
||||||
- metoda volá přímo sebe sama
|
|
||||||
- je vidět na první pohled
|
|
||||||
|
|
||||||
## Nepřímá rekurze
|
|
||||||
|
|
||||||
- `a` volá `b`, `b` volá `a`
|
|
||||||
|
|
||||||
## Problémy rekurze
|
|
||||||
|
|
||||||
- problémy s hloubkou zásobníku
|
|
||||||
- spíše programátorská chyba - **přetečení zásobníku**
|
|
||||||
- pro mnoho praktických problémů je rekurze dostatečná
|
|
||||||
- Java umožňuje nastavit velikost zásobníku
|
|
||||||
- často lze zapsat do nerekurzní formy
|
|
||||||
- nerekurzivní zápis je **často rychlejší**
|
|
||||||
- zrychlení se projeví, pokud je samotný vykonávaný kód triviální
|
|
||||||
- někdy je přepsání poměrně složité
|
|
24
KIV PPA2/02. Rekurzivní programy.md
Normal file
24
KIV PPA2/02. Rekurzivní programy.md
Normal file
|
@ -0,0 +1,24 @@
|
||||||
|
# Rekurzivní programy
|
||||||
|
|
||||||
|
- programy, které volají sami sebe
|
||||||
|
- rekurze, musí někdy skončit!
|
||||||
|
|
||||||
|
## Přímá rekurze
|
||||||
|
|
||||||
|
- metoda volá přímo sebe sama
|
||||||
|
- je vidět na první pohled
|
||||||
|
|
||||||
|
## Nepřímá rekurze
|
||||||
|
|
||||||
|
- `a` volá `b`, `b` volá `a`
|
||||||
|
|
||||||
|
## Problémy rekurze
|
||||||
|
|
||||||
|
- problémy s hloubkou zásobníku
|
||||||
|
- spíše programátorská chyba - **přetečení zásobníku**
|
||||||
|
- pro mnoho praktických problémů je rekurze dostatečná
|
||||||
|
- Java umožňuje nastavit velikost zásobníku
|
||||||
|
- často lze přepsat do nerekurzivní formy
|
||||||
|
- nerekurzivní zápis je **často rychlejší**
|
||||||
|
- zrychlení se projeví, pokud je samotný vykonávaný kód triviální
|
||||||
|
- někdy je přepsání poměrně složité
|
|
@ -1,16 +1,16 @@
|
||||||
# Výpočetní složitost
|
# Výpočetní složitost
|
||||||
|
|
||||||
- doba výpočtu T(n) v závislosti na vstupu n
|
- doba výpočtu $T(n)$ v závislosti na vstupu $n$
|
||||||
- je důležité určit, co je důležité
|
- je důležité určit, co je důležité
|
||||||
- zajímá nás, co se děje, když n roste
|
- zajímá nás, co se děje, když $n$ roste
|
||||||
- různé funkce rostou různě rychle
|
- různé funkce rostou různě rychle
|
||||||
- druhy algoritmů
|
- druhy algoritmů
|
||||||
- rychle rostoucí funkce = neefektivní algoritmus
|
- rychle rostoucí funkce = neefektivní algoritmus
|
||||||
- pomalu rostoucí funkce = efektivní algoritmus
|
- pomalu rostoucí funkce = efektivní algoritmus
|
||||||
- záleží na tom, jestli se funkce vejde pod jinou
|
- záleží na tom, jestli se funkce vejde pod jinou
|
||||||
- například lineární pod kubickou
|
- například lineární pod kubickou
|
||||||
- ne hned, ale od nějakého $n_0$ ano
|
- nemusí se vejít hned, ale třeba od nějakého $n_0$ ano
|
||||||
- nezáleží na násobku, jen to $n_{0}$ bude dál
|
- nezáleží na násobku $n$, jen to $n_{0}$ bude dál
|
||||||
|
|
||||||
## O-notace
|
## O-notace
|
||||||
|
|
||||||
|
@ -76,7 +76,7 @@ Význam funkcí může být:
|
||||||
- čas výpočtu pro nejhorší možný vstup velikosti n
|
- čas výpočtu pro nejhorší možný vstup velikosti n
|
||||||
- průměrný čas výpočtu pro vstup velikosti n
|
- průměrný čas výpočtu pro vstup velikosti n
|
||||||
- počet instrukcí pro ...
|
- počet instrukcí pro ...
|
||||||
- množství paměti nutné pro zpracování ...
|
- množství paměti nutné pro zpr# 1020acování ...
|
||||||
- ...
|
- ...
|
||||||
|
|
||||||
Je ale potřeba nesrovnávat hrušky s pomeranči.
|
Je ale potřeba nesrovnávat hrušky s pomeranči.
|
||||||
|
@ -85,5 +85,5 @@ Je ale potřeba nesrovnávat hrušky s pomeranči.
|
||||||
## Určení výpočetní složitosti programu
|
## Určení výpočetní složitosti programu
|
||||||
|
|
||||||
- je potřeba určit funkci $g(n)$
|
- je potřeba určit funkci $g(n)$
|
||||||
- při určování můžeme zanedbat časy jednotlivých instrukcí, **pokud jsou opravdu konstatní** (nezávislá na parametru n)
|
- při určování můžeme zanedbat časy jednotlivých instrukcí, **pokud jsou opravdu konstantní** (nezávislé na parametru $n$)
|
||||||
- výpočetní složitost neřeší rozdílné výkony počítačů
|
- výpočetní složitost neřeší rozdílné výkony počítačů
|
|
@ -95,7 +95,7 @@ Nalezení pořadí (indexů) pro množinu prvků podle nějakého uspořádání
|
||||||
- procházíme obě posloupnosti současně (držíme aktuální index pro obě)
|
- procházíme obě posloupnosti současně (držíme aktuální index pro obě)
|
||||||
- do výsledné posloupnosti zapíšeme menší ze dvou aktuálních prvků
|
- do výsledné posloupnosti zapíšeme menší ze dvou aktuálních prvků
|
||||||
- v příslušné posloupnosti se posuneme na další prvek
|
- v příslušné posloupnosti se posuneme na další prvek
|
||||||
- efentivní implementace:
|
- efektivní implementace:
|
||||||
- pracuje s úseky původního pole a eliminuje testování konce polí A a B
|
- pracuje s úseky původního pole a eliminuje testování konce polí A a B
|
||||||
- alokuje se dočasné pole
|
- alokuje se dočasné pole
|
||||||
- v poli se vytvoří tzv. bitonická posloupnost
|
- v poli se vytvoří tzv. bitonická posloupnost
|
25
KIV PPA2/05. Abstraktní datové typy.md
Normal file
25
KIV PPA2/05. Abstraktní datové typy.md
Normal file
|
@ -0,0 +1,25 @@
|
||||||
|
# Abstraktní datové typy
|
||||||
|
|
||||||
|
- abstraktní - nezabývá se rozdíly, ale tím, co je **společné**
|
||||||
|
- definují možné operace s daty
|
||||||
|
- nedefinují způsob uložení dat ani provedení operací (implementaci)
|
||||||
|
|
||||||
|
**ADT vs rozhraní**
|
||||||
|
- ADT můžou být implementovány různě v různých jazycích
|
||||||
|
- rozhraní jen způsob implementace ADT v Javě
|
||||||
|
|
||||||
|
**Kolekce**
|
||||||
|
- datové struktury, které uchovávají sadu prvků
|
||||||
|
- umožňují operace s daty
|
||||||
|
- přidat prvek (na začátek, na konec, za/před prvek, s nějakým klíčem, ...)
|
||||||
|
- vybrat prvek (na začátku, na konci, na indexu, s extrémním klíčem, ...)
|
||||||
|
- odebrat prvek (na začátku, na konci, na indexu, s extrémním klíčem, ...)
|
||||||
|
|
||||||
|
**Implementace ADT**
|
||||||
|
- určuje složitost operací
|
||||||
|
- obvykle reprezentována třídou
|
||||||
|
|
||||||
|
**Úkol programátora**
|
||||||
|
- vybrat vhodnou ADT
|
||||||
|
- vybrat vhodnou implementaci ADT
|
||||||
|
- vědět, co ADT dělá (jaká je složitost operací)
|
|
@ -1,29 +1,3 @@
|
||||||
# Abstraktní datové typy
|
|
||||||
|
|
||||||
- abstraktní - nezabývá se rozdíly, ale tím, co je **společné**
|
|
||||||
- definují možné operace s daty
|
|
||||||
- nedefinují způsob uložení dat ani provedení operací (implementaci)
|
|
||||||
|
|
||||||
**ADT vs rozhraní**
|
|
||||||
- ADT můžou být implementovány různě v různých jazycích
|
|
||||||
- rozhraní jen způsob implementace ADT v Javě
|
|
||||||
|
|
||||||
**Kolekce**
|
|
||||||
- datové struktury, které uchovávání sadu prvků
|
|
||||||
- umožňují operace s daty
|
|
||||||
- přidat prvek (na začátek, na konec, za/před prvek, s nějakým klíčem, ...)
|
|
||||||
- vybrat prvek (na začátku, na konci, na indexu, s extrémním klíčem, ...)
|
|
||||||
- odebrat prvek (na začátku, na konci, na indexu, s extrémním klíčem, ...)
|
|
||||||
|
|
||||||
**Implementace ADT**
|
|
||||||
- určuje složitost operací
|
|
||||||
- obvykle reprezentována třídou
|
|
||||||
|
|
||||||
**Úkol programátora**
|
|
||||||
- vybrat vhodnou ADT
|
|
||||||
- vybrat vhodnou implementaci ADT
|
|
||||||
- vědět, co ADT dělá (jaká je složitost operací)
|
|
||||||
|
|
||||||
# Zásobník
|
# Zásobník
|
||||||
|
|
||||||
- abstraktní datová struktura
|
- abstraktní datová struktura
|
||||||
|
@ -69,7 +43,7 @@
|
||||||
- $n = 2^k + 1, o = 2^{k+1} - 1$
|
- $n = 2^k + 1, o = 2^{k+1} - 1$
|
||||||
- $o = 2(2k) - 1 = 2(2k + 1) - 3 = 2n - 3 < 2n$
|
- $o = 2(2k) - 1 = 2(2k + 1) - 3 = 2n - 3 < 2n$
|
||||||
- **závěr**:
|
- **závěr**:
|
||||||
- složitost oprace přidání je $\mathcal{O}(n)$
|
- složitost operace přidání je $\mathcal{O}(n)$
|
||||||
- průměrná složitost je $\Theta(1)$
|
- průměrná složitost je $\Theta(1)$
|
||||||
- při zvětšování **o konstantu** to neplatí
|
- při zvětšování **o konstantu** to neplatí
|
||||||
- přidání n prvků $\Omega(n^2)$
|
- přidání n prvků $\Omega(n^2)$
|
||||||
|
@ -104,7 +78,7 @@ Tyto aspekty není potřeba se učit, vyplývají ze způsobu implementace.
|
||||||
|
|
||||||
#### Použití z klientské třídy
|
#### Použití z klientské třídy
|
||||||
|
|
||||||
- použití obou implementací je úplně stejné
|
- použití obou implementací je úplně stejné
|
||||||
- uživatel vůbec nemusí vědět, co se děje uvnitř
|
- uživatel vůbec nemusí vědět, co se děje uvnitř
|
||||||
- vnitřní data jsou udržována v konzistentním stavu
|
- vnitřní data jsou udržována v konzistentním stavu
|
||||||
|
|
45
KIV PPA2/07. Odstranění rekurze.md
Normal file
45
KIV PPA2/07. Odstranění rekurze.md
Normal file
|
@ -0,0 +1,45 @@
|
||||||
|
# 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íme 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
|
42
KIV PPA2/08. ADT Fronta.md
Normal file
42
KIV PPA2/08. ADT Fronta.md
Normal file
|
@ -0,0 +1,42 @@
|
||||||
|
# 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
|
||||||
|
- odebrání prvku na 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)$
|
34
KIV PPA2/09. Třídy s typovým parametrem.md
Normal file
34
KIV PPA2/09. Třídy s typovým parametrem.md
Normal file
|
@ -0,0 +1,34 @@
|
||||||
|
# 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
|
||||||
|
- **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`
|
||||||
|
- **problém**
|
||||||
|
- je potřeba ji vytvořit pro každý datový typ
|
||||||
|
|
||||||
|
**Generická třída**
|
||||||
|
- **"správné" řešení**
|
||||||
|
- třída s typovým parametrem `class MyStack<T>`
|
||||||
|
- 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<T extends IProcessable>`
|
||||||
|
- pokud potřebujeme použít nějakou metodu tohoto rozhraní ve třídě, můžeme `Object` přetypovat na `T`
|
|
@ -16,7 +16,7 @@ Jak specifikovat pozici?
|
||||||
- ukazuje na prvek
|
- ukazuje na prvek
|
||||||
- některé operace problematické (např. vložení - před nebo za prvek?)
|
- některé operace problematické (např. vložení - před nebo za prvek?)
|
||||||
- ukazuje mezi prvky
|
- ukazuje mezi prvky
|
||||||
- jednožnačné vkládání: sem
|
- jednoznačné vkládání: sem
|
||||||
- vybírání/odebírání dohodou - třeba prvek napravo
|
- vybírání/odebírání dohodou - třeba prvek napravo
|
||||||
|
|
||||||
### Implementace spojovou strukturou
|
### Implementace spojovou strukturou
|
||||||
|
@ -43,7 +43,7 @@ Jak specifikovat pozici?
|
||||||
|
|
||||||
- seznam neumožňuje prácí **na více místech**
|
- seznam neumožňuje prácí **na více místech**
|
||||||
- vznik odděleného ukazovátka od dat - **iterátoru** (návrhový vzor)
|
- vznik odděleného ukazovátka od dat - **iterátoru** (návrhový vzor)
|
||||||
- třída, která má aktuální index `current` a referenci `list
|
- třída, která má aktuální index `current` a referenci `list`
|
||||||
- stejná implementace jako u seznamu (místo `first` se použije `list.first`)`
|
- stejná implementace jako u seznamu (místo `first` se použije `list.first`)`
|
||||||
|
|
||||||
**Operace**
|
**Operace**
|
||||||
|
@ -75,84 +75,4 @@ Jak specifikovat pozici?
|
||||||
- pro index následovníka (`next`) - prázdného či obsazeného prvku
|
- pro index následovníka (`next`) - prázdného či obsazeného prvku
|
||||||
- index začátku `first`
|
- index začátku `first`
|
||||||
- index volného pole `empty`
|
- index volného pole `empty`
|
||||||
- index aktuálního prvku `current`
|
- index aktuálního prvku `current`
|
||||||
|
|
||||||
# Kolekce v Javě
|
|
||||||
|
|
||||||
Java poskytuje knihovní třídy pro základní implementaci kolekcí
|
|
||||||
|
|
||||||
### Třída `LinkedList<T>`
|
|
||||||
|
|
||||||
- spojová datová struktura
|
|
||||||
|
|
||||||
**Operace**
|
|
||||||
- operace v $\mathcal O(1)$
|
|
||||||
- `void addFirst(T)`, `void addLast(T)`
|
|
||||||
- `T getFirst()`, `T getLast()`
|
|
||||||
- `void removeFirst()`, `void removeLast()`
|
|
||||||
- operace v $\Omega(n)$
|
|
||||||
- `void add(int, T)` - vložení na daný index
|
|
||||||
- `T get(int)` - získání z indexu
|
|
||||||
- `void remove(int)` - smazání z indexu
|
|
||||||
- `Iterator<T> iterator()`
|
|
||||||
- `ListIterator<T> listIterator()` - lepší iterátor
|
|
||||||
|
|
||||||
### Třída `ArrayList<T>`
|
|
||||||
|
|
||||||
- dynamické pole
|
|
||||||
|
|
||||||
**Operace**
|
|
||||||
- operace v $\mathcal O(1)$
|
|
||||||
- `void add(T)`
|
|
||||||
- `T get(int)`
|
|
||||||
- operace v $\Omega(n)$
|
|
||||||
- `void remove(int)
|
|
||||||
- operace pro získání iterátorů - ale s **vyšší složitostí**!
|
|
||||||
|
|
||||||
### Třída `Iterator<T>`
|
|
||||||
|
|
||||||
**Operace**
|
|
||||||
- `T next()` - vrátí přeskočený prvek a posune se dopředu
|
|
||||||
- na konci vyhodí výjimku
|
|
||||||
- `boolean hasNext()` - existence dalšího prvku
|
|
||||||
- `void remove()` - odstraní poslední prvek vrácený metodou `next()`
|
|
||||||
- před dalším odstraněním potřeba zavolat `next()`
|
|
||||||
- chybí:
|
|
||||||
- návrat na začátek (stačí si vyžádat nový iterátor)
|
|
||||||
- metoda pro vložení prvku
|
|
||||||
|
|
||||||
**Vylepšený `ListIterator<T>`**
|
|
||||||
- má navíc:
|
|
||||||
- `T previous()` - vrátí hodnotu předchozího prvku a posune iterátor zpět
|
|
||||||
- na začátku vyhodí výjimku
|
|
||||||
- `void add(T)` - vloží prvek na pozici iterátoru
|
|
||||||
|
|
||||||
### Rozhraní `Queue<T>`
|
|
||||||
|
|
||||||
- rozhraní fronty
|
|
||||||
- `LinkedList<T>` toto rozhraní implementuje
|
|
||||||
|
|
||||||
**Operace**
|
|
||||||
- `void add()`
|
|
||||||
- `T element()`
|
|
||||||
- `T remove()`
|
|
||||||
|
|
||||||
### Třída `Stack<T>`
|
|
||||||
|
|
||||||
implementace zásobníku dynamickým polem - `ArrayList`
|
|
||||||
- stejné metody poskytuje i `LinkedList`
|
|
||||||
|
|
||||||
**Operace**
|
|
||||||
- `void push(T)`
|
|
||||||
- `T pop()`
|
|
||||||
- `T peek()`
|
|
||||||
|
|
||||||
### Obecná zásada
|
|
||||||
|
|
||||||
Kolekce v čase $\mathcal O(1)$ umí buď
|
|
||||||
1) vybrat prvek na specifickém indexu, anebo
|
|
||||||
2) vyjmout/vložit prvek na pozici iterátoru,
|
|
||||||
|
|
||||||
ale nikdy ne obojí současně!
|
|
||||||
|
|
||||||
Najít i-tý prvek ve spojovém seznamu zabere vždy $\Omega(n)$.
|
|
79
KIV PPA2/11. Kolekce v Javě.md
Normal file
79
KIV PPA2/11. Kolekce v Javě.md
Normal file
|
@ -0,0 +1,79 @@
|
||||||
|
# Kolekce v Javě
|
||||||
|
|
||||||
|
Java poskytuje knihovní třídy pro základní implementaci kolekcí
|
||||||
|
|
||||||
|
### Třída `LinkedList<T>`
|
||||||
|
|
||||||
|
- spojová datová struktura
|
||||||
|
|
||||||
|
**Operace**
|
||||||
|
- operace v $\mathcal O(1)$
|
||||||
|
- `void addFirst(T)`, `void addLast(T)`
|
||||||
|
- `T getFirst()`, `T getLast()`
|
||||||
|
- `void removeFirst()`, `void removeLast()`
|
||||||
|
- operace v $\Omega(n)$
|
||||||
|
- `void add(int, T)` - vložení na daný index
|
||||||
|
- `T get(int)` - získání z indexu
|
||||||
|
- `void remove(int)` - smazání z indexu
|
||||||
|
- `Iterator<T> iterator()`
|
||||||
|
- `ListIterator<T> listIterator()` - lepší iterátor
|
||||||
|
|
||||||
|
### Třída `ArrayList<T>`
|
||||||
|
|
||||||
|
- dynamické pole
|
||||||
|
|
||||||
|
**Operace**
|
||||||
|
- operace v $\mathcal O(1)$
|
||||||
|
- `void add(T)`
|
||||||
|
- `T get(int)`
|
||||||
|
- operace v $\Omega(n)$
|
||||||
|
- `void remove(int)`
|
||||||
|
- operace pro získání iterátorů - ale s **vyšší složitostí**!
|
||||||
|
|
||||||
|
### Třída `Iterator<T>`
|
||||||
|
|
||||||
|
**Operace**
|
||||||
|
- `T next()` - vrátí přeskočený prvek a posune se dopředu
|
||||||
|
- na konci vyhodí výjimku
|
||||||
|
- `boolean hasNext()` - existence dalšího prvku
|
||||||
|
- `void remove()` - odstraní poslední prvek vrácený metodou `next()`
|
||||||
|
- před dalším odstraněním potřeba zavolat `next()`
|
||||||
|
- chybí:
|
||||||
|
- návrat na začátek (stačí si vyžádat nový iterátor)
|
||||||
|
- metoda pro vložení prvku
|
||||||
|
|
||||||
|
**Vylepšený `ListIterator<T>`**
|
||||||
|
- má navíc:
|
||||||
|
- `T previous()` - vrátí hodnotu předchozího prvku a posune iterátor zpět
|
||||||
|
- na začátku vyhodí výjimku
|
||||||
|
- `void add(T)` - vloží prvek na pozici iterátoru
|
||||||
|
|
||||||
|
### Rozhraní `Queue<T>`
|
||||||
|
|
||||||
|
- rozhraní fronty
|
||||||
|
- `LinkedList<T>` toto rozhraní implementuje
|
||||||
|
|
||||||
|
**Operace**
|
||||||
|
- `void add()`
|
||||||
|
- `T element()`
|
||||||
|
- `T remove()`
|
||||||
|
|
||||||
|
### Třída `Stack<T>`
|
||||||
|
|
||||||
|
implementace zásobníku dynamickým polem - `ArrayList`
|
||||||
|
- stejné metody poskytuje i `LinkedList`
|
||||||
|
|
||||||
|
**Operace**
|
||||||
|
- `void push(T)`
|
||||||
|
- `T pop()`
|
||||||
|
- `T peek()`
|
||||||
|
|
||||||
|
### Obecná zásada
|
||||||
|
|
||||||
|
Kolekce v čase $\mathcal O(1)$ umí buď
|
||||||
|
1) vybrat prvek na specifickém indexu, anebo
|
||||||
|
2) vyjmout/vložit prvek na pozici iterátoru,
|
||||||
|
|
||||||
|
ale nikdy ne obojí současně!
|
||||||
|
|
||||||
|
Najít i-tý prvek ve spojovém seznamu zabere vždy $\Omega(n)$.
|
|
@ -36,7 +36,7 @@ Ideálně by měly mít všechny (kromě všech klíčů) složitost $\Theta(1)$
|
||||||
**Tabulka s přímým adresováním**
|
**Tabulka s přímým adresováním**
|
||||||
- pole, kde index je klíč
|
- pole, kde index je klíč
|
||||||
- problém:
|
- problém:
|
||||||
- často neznáme rozsah možnách klíčů
|
- často neznáme rozsah možných klíčů
|
||||||
- počet přípustných klíčů může být velmi velký nebo nekonečný
|
- počet přípustných klíčů může být velmi velký nebo nekonečný
|
||||||
- neřeší složitější klíče
|
- neřeší složitější klíče
|
||||||
- výhoda: splňuje $\Theta(1)$
|
- výhoda: splňuje $\Theta(1)$
|
|
@ -74,7 +74,7 @@ Operace se můžou lišit podle druhu stromu (binární, uspořádaný, ...).
|
||||||
- předek vrcholu s indexem i leží na indexu i/2 (celočíselně)
|
- předek vrcholu s indexem i leží na indexu i/2 (celočíselně)
|
||||||
- strom o hloubce h má vrcholy s maximálním indexem $2^{h+1} - 1$
|
- strom o hloubce h má vrcholy s maximálním indexem $2^{h+1} - 1$
|
||||||
- **reprezentace vrcholu**:
|
- **reprezentace vrcholu**:
|
||||||
- reprezenntován svým indexem
|
- reprezentován svým indexem
|
||||||
- musí mu být přiřazena data, která jsou uložena v poli
|
- musí mu být přiřazena data, která jsou uložena v poli
|
||||||
- **data přiřazená vrcholu**:
|
- **data přiřazená vrcholu**:
|
||||||
- uložená do pole na index vrcholu
|
- uložená do pole na index vrcholu
|
||||||
|
@ -88,7 +88,7 @@ Operace se můžou lišit podle druhu stromu (binární, uspořádaný, ...).
|
||||||
- **nevýhody**:
|
- **nevýhody**:
|
||||||
- pouze pro binární stromy
|
- pouze pro binární stromy
|
||||||
- musíme předem znát počet prvků
|
- musíme předem znát počet prvků
|
||||||
- alokuje se paměť i přo nepřítomné prvky (nebo referenci)
|
- alokuje se paměť i pro nepřítomné prvky (nebo referenci)
|
||||||
|
|
||||||
Pozn.: **Úplný binární strom**
|
Pozn.: **Úplný binární strom**
|
||||||
- pro určitý index k platí:
|
- pro určitý index k platí:
|
||||||
|
@ -119,13 +119,14 @@ Pozn.: **Úplný binární strom**
|
||||||
- zahájení průchodu zavoláním metody `preorder/inorder/postorder` nad kořenem
|
- zahájení průchodu zavoláním metody `preorder/inorder/postorder` nad kořenem
|
||||||
|
|
||||||
### Binární vyhledávací strom (BST)
|
### Binární vyhledávací strom (BST)
|
||||||
|
|
||||||
- reprezentuje uspořádanou množinu prvků
|
- reprezentuje uspořádanou množinu prvků
|
||||||
- prvky seřazené pomocí klíče - nejjednodušeji `int`
|
- prvky seřazené pomocí klíče - nejjednodušeji `int`
|
||||||
- strom je pouze implementací, ADT hierarchický není
|
- strom je pouze implementací, ADT hierarchický není
|
||||||
|
|
||||||
**Operace**
|
**Operace**
|
||||||
- vložení prvku s klíčem
|
- vložení prvku s klíčem
|
||||||
- oderání prvku s klíčem
|
- odebrání prvku s klíčem
|
||||||
- zjištění přítomnosti prvku s klíčem
|
- zjištění přítomnosti prvku s klíčem
|
||||||
- nalezení největšího a nejmenšího klíče
|
- nalezení největšího a nejmenšího klíče
|
||||||
- vybrání všech prvků v pořadí klíčů
|
- vybrání všech prvků v pořadí klíčů
|
|
@ -6,7 +6,7 @@
|
||||||
### Druhy grafů
|
### Druhy grafů
|
||||||
|
|
||||||
- **Orientovaný graf**
|
- **Orientovaný graf**
|
||||||
- podchybuje nesymetrické vztahy
|
- podchycuje nesymetrické vztahy
|
||||||
|
|
||||||
### Formální definice
|
### Formální definice
|
||||||
|
|
||||||
|
@ -24,7 +24,7 @@
|
||||||
- $\vert V\vert$ - počet vrcholů grafu
|
- $\vert V\vert$ - počet vrcholů grafu
|
||||||
- $\vert E\vert$ - počet hran grafu
|
- $\vert E\vert$ - počet hran grafu
|
||||||
+ $V(G)$ - množina vrcholů grafu $G$
|
+ $V(G)$ - množina vrcholů grafu $G$
|
||||||
+ $V(E)$ - množina hran grafu $G$
|
+ $E(G)$ - množina hran grafu $G$
|
||||||
- $y \in V$ je sousedem $x \in V$ právě když
|
- $y \in V$ je sousedem $x \in V$ právě když
|
||||||
- existuje orientovaná hrana $E = (x, y)$
|
- existuje orientovaná hrana $E = (x, y)$
|
||||||
- existuje neorientovaná hrana $E, x \in E, y \in E$
|
- existuje neorientovaná hrana $E, x \in E, y \in E$
|
||||||
|
@ -200,4 +200,57 @@
|
||||||
+ celkem
|
+ celkem
|
||||||
+ úplný, popř. hustý graf nebo implementace sousednosti maticí: $\Omega(\vert V\vert^2)$
|
+ úplný, popř. hustý graf nebo implementace sousednosti maticí: $\Omega(\vert V\vert^2)$
|
||||||
+ implementace sousednosti seznamem: $\mathcal{O}(\vert V\vert + \vert E\vert)$
|
+ implementace sousednosti seznamem: $\mathcal{O}(\vert V\vert + \vert E\vert)$
|
||||||
+ graf může mít počet hran až $\vert V\vert^2$
|
+ graf může mít počet hran až $\vert V\vert^2$
|
||||||
|
|
||||||
|
**Strom dosažitelnosti**
|
||||||
|
- tvoří se z nějakého určeného vrcholu (kořen)
|
||||||
|
- ukazuje, jaká je nejkratší cesta do ostatních vrcholů
|
||||||
|
- reprezentován polem, kde na indexu vrcholu je uložen předek
|
||||||
|
- nemusí být jednoznačný (může existovat více nejkratších cest)
|
||||||
|
|
||||||
|
#### Prohledávánı́ do hloubky (DFS)
|
||||||
|
|
||||||
|
- Depth-First Search
|
||||||
|
- algoritmus postupuje do většı́ vzdálenosti od počátečnı́ho vrcholu, pokud může
|
||||||
|
+ předpokládáme, že označenı́ (mark) je před volánı́m DFS inicializováno na 0 pro všechny vrcholy
|
||||||
|
+ DFS je potřeba doplnit o nějaký užitečný kód
|
||||||
|
+ záleží to na řešeném problému
|
||||||
|
|
||||||
|
**Značenı́ vrcholů**
|
||||||
|
- nezpracovaný (”bı́lá”), kód 0
|
||||||
|
- rozpracovaný (”šedá”), kód 1
|
||||||
|
- dokončený (”černá”), kód 2
|
||||||
|
|
||||||
|
**Složitost**
|
||||||
|
- rekurzivní metoda se pro každý vrchol volá pouze jednou - $\Omega(\vert V\vert)$
|
||||||
|
- pro každý vrchol se prochází seznam hran:
|
||||||
|
- reprezentace maticí - $\Omega(\vert V\vert^2)$
|
||||||
|
- reprezentace seznamem - $\mathcal{O}(\vert E\vert)$
|
||||||
|
- celkem: $\mathcal{O}(\vert V\vert + \vert E\vert)$ při reprezentaci seznamem
|
||||||
|
- může být i $\Omega(\vert V\vert^2)$, pokud $\vert E\vert = k\vert V\vert^2$
|
||||||
|
|
||||||
|
**Použití DFS**
|
||||||
|
- Zjištění dosažitelnosti vrcholu
|
||||||
|
- pokud předpokládáme, že bude vrchol daleko, je DFS vhodnější než BFS
|
||||||
|
+ Zjištění cyklu v grafu
|
||||||
|
+ vrchol označíme jedničkou a poté ho znovu hledáme
|
||||||
|
+ Topologické řazení
|
||||||
|
+ prvně je potřeba ověřit, že graf nemá cykly
|
||||||
|
+ vrcholy jsou činnosti, hrany jsou závislosti
|
||||||
|
+ hrana $A \to B$ značí, že se prvně musí vykonat A a potom až B
|
||||||
|
+ pomocí DFS můžeme snadno určit pořadí činností (pomocí otočeného grafu)
|
||||||
|
|
||||||
|
**DFS bez rekurze**
|
||||||
|
- pravděpodobně nastanou problémy s hloubkou zásobníku
|
||||||
|
+ vystačíme si se zásobníkem celých čísel (vrcholů)
|
||||||
|
+ `segment` (jaký je stav vrcholu) je v označení vrcholu (`mark`)
|
||||||
|
|
||||||
|
**Nejkratší cesta v ohodnoceném grafu**
|
||||||
|
- velmi častý problém
|
||||||
|
- ohodnocení: čas, vzdálenost, ...
|
||||||
|
- úkol: nalézt nejkratší vzdálenost ke všem vrcholům
|
||||||
|
- **Dijkstrův algoritmus**
|
||||||
|
- je potřeba prioritní fronta
|
||||||
|
- přidání dvojice vrchol + ohodnocení
|
||||||
|
- vybrání/odebrání vrcholu s nejmenším ohodnocením
|
||||||
|
- změna ohodnocení vrcholu
|
|
@ -75,21 +75,4 @@
|
||||||
+ budeme je vytvářet od konce stromu (od listů)
|
+ budeme je vytvářet od konce stromu (od listů)
|
||||||
- složitost
|
- složitost
|
||||||
- nejhorší a očekávaná: $\Theta(n \log(n))$
|
- nejhorší a očekávaná: $\Theta(n \log(n))$
|
||||||
- paměťová: $\Theta(1)$
|
- paměťová: $\Theta(1)$
|
||||||
|
|
||||||
# Rekapitulace ADT
|
|
||||||
|
|
||||||
**Přístup k datům pomocí indexů**
|
|
||||||
|
|
||||||
| | vybrání | odebrání | přidání |
|
|
||||||
| ----------------- | ----------- | ---------------------------- | ---------------------------- |
|
|
||||||
| spojová struktura | $\Theta(n)$ | $\Theta(1)$ pokud byl vybrán | $\Theta(1)$ pokud byl vybrán |
|
|
||||||
| dynamické pole | $\Theta(1)$ | $\Theta(n)$ | $\Theta(n)$ |
|
|
||||||
|
|
||||||
**Přístup k datům pomocí klíče**
|
|
||||||
|
|
||||||
| | přidání | odebrání | vybrání | vybrání maxima | odebrání maxima |
|
|
||||||
| ------- | ----------------- | ----------------- | ----------------- | ----------------- | ----------------- |
|
|
||||||
| Tabulka | $\Theta(1)$ | $\Theta(1)$ | $\Theta(1)$ | $\Theta(n)$ | $\Theta(n)$ |
|
|
||||||
| BST | $\Theta(\log(n))$ | $\Theta(\log(n))$ | $\Theta(\log(n))$ | $\Theta(\log(n))$ | $\Theta(\log(n))$ |
|
|
||||||
| Halda | $\Theta(\log(n))$ | N/A | N/A | $\Theta(1)$ | $\Theta(\log(n))$ |
|
|
16
KIV PPA2/16. Rekapitulace ADT.md
Normal file
16
KIV PPA2/16. Rekapitulace ADT.md
Normal file
|
@ -0,0 +1,16 @@
|
||||||
|
# Rekapitulace ADT
|
||||||
|
|
||||||
|
**Přístup k datům pomocí indexů**
|
||||||
|
|
||||||
|
| | vybrání | odebrání | přidání |
|
||||||
|
| ----------------- | ----------- | ---------------------------- | ---------------------------- |
|
||||||
|
| spojová struktura | $\Theta(n)$ | $\Theta(1)$ pokud byl vybrán | $\Theta(1)$ pokud byl vybrán |
|
||||||
|
| dynamické pole | $\Theta(1)$ | $\Theta(n)$ | $\Theta(n)$ |
|
||||||
|
|
||||||
|
**Přístup k datům pomocí klíče**
|
||||||
|
|
||||||
|
| | přidání | odebrání | vybrání | vybrání maxima | odebrání maxima |
|
||||||
|
| ------- | ----------------- | ----------------- | ----------------- | ----------------- | ----------------- |
|
||||||
|
| Tabulka | $\Theta(1)$ | $\Theta(1)$ | $\Theta(1)$ | $\Theta(n)$ | $\Theta(n)$ |
|
||||||
|
| BST | $\Theta(\log(n))$ | $\Theta(\log(n))$ | $\Theta(\log(n))$ | $\Theta(\log(n))$ | $\Theta(\log(n))$ |
|
||||||
|
| Halda | $\Theta(\log(n))$ | N/A | N/A | $\Theta(1)$ | $\Theta(\log(n))$ |
|
|
@ -1,120 +0,0 @@
|
||||||
# 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<T>`
|
|
||||||
- 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<T extends IProcessable>`
|
|
||||||
- pokud potřebujeme použít nějakou metodu tohoto rozhraní ve třídě, můžeme `Object` přetypovat na `T`
|
|
|
@ -1,57 +0,0 @@
|
||||||
# Grafy 2
|
|
||||||
|
|
||||||
#### Prohledávání do šířky (BFS)
|
|
||||||
|
|
||||||
**Strom dosažitelnosti**
|
|
||||||
- tvoří se z nějakého určeného vrcholu (kořen)
|
|
||||||
- ukazuje, jaká je nejkratší cesta do ostatních vrcholů
|
|
||||||
- reprezentován polem, kde na indexu vrcholu je uložen předek
|
|
||||||
- nemusí být jednoznačný (může existovat více nejkratších cest)
|
|
||||||
|
|
||||||
|
|
||||||
#### Prohledávánı́ do hloubky (DFS)
|
|
||||||
|
|
||||||
- Depth-First Search
|
|
||||||
- algoritmus postupuje do většı́ vzdálenosti od počátečnı́ho vrcholu, pokud může
|
|
||||||
+ předpokládáme, že označenı́ (mark) je před volánı́m DFS inicializováno na 0 pro všechny vrcholy
|
|
||||||
+ DFS je potřeba doplnit o nějaký užitečný kód
|
|
||||||
+ záleží to na řešeném problému
|
|
||||||
|
|
||||||
**Značenı́ vrcholů**
|
|
||||||
- nezpracovaný (”bı́lá”), kód 0
|
|
||||||
- rozpracovaný (”šedá”), kód 1
|
|
||||||
- dokončený (”černá”), kód 2
|
|
||||||
|
|
||||||
**Složitost**
|
|
||||||
- rekurzivní metoda se pro každý vrchol volá pouze jednou - $\Omega(\vert V\vert)$
|
|
||||||
- pro každý vrchol se prochází seznam hran:
|
|
||||||
- reprezentace maticí - $\Omega(\vert V\vert^2)$
|
|
||||||
- reprezentace seznamem - $\mathcal{O}(\vert E\vert)$
|
|
||||||
- celkem: $\mathcal{O}(\vert V\vert + \vert E\vert)$ při reprezentaci seznamem
|
|
||||||
- může být i $\Omega(\vert V\vert^2)$, pokud $\vert E\vert = k\vert V\vert^2$
|
|
||||||
|
|
||||||
**Použití DFS**
|
|
||||||
- Zjištění dosažitelnosti vrcholu
|
|
||||||
- pokud předpokládáme, že bude vrchol daleko, je DFS vhodnější než BFS
|
|
||||||
+ Zjištění cyklu v grafu
|
|
||||||
+ vrchol označíme jedničkou a poté ho znovu hledáme
|
|
||||||
+ Topologické řazení
|
|
||||||
+ prvně je potřeba ověřit, že graf nemá cykly
|
|
||||||
+ vrcholy jsou činnosti, hrany jsou závislosti
|
|
||||||
+ hrana $A \to B$ značí, že se prvně musí vykonat A a potom až B
|
|
||||||
+ pomocí DFS můžeme snadno určit pořadí činností (pomocí otočeného grafu)
|
|
||||||
|
|
||||||
**DFS bez rekurze**
|
|
||||||
- pravděpodobně nastanou problémy s hloubkou zásobníku
|
|
||||||
+ vystačíme si se zásobníkem celých čísel (vrcholů)
|
|
||||||
+ `segment` (jaký je stav vrcholu) je v označení vrcholu (`mark`)
|
|
||||||
|
|
||||||
**Nejkratší cesta v ohodnoceném grafu**
|
|
||||||
- velmi častý problém
|
|
||||||
- ohodnocení: čas, vzdálenost, ...
|
|
||||||
- úkol: nalézt nejkratší vzdálenost ke všem vrcholům
|
|
||||||
- **Dijkstrův algoritmus**
|
|
||||||
- je potřeba prioritní fronta
|
|
||||||
- přidání dvojice vrchol + ohodnocení
|
|
||||||
- vybrání/odebrání vrcholu s nejmenším ohodnocením
|
|
||||||
- změna ohodnocení vrcholu
|
|
Loading…
Reference in a new issue