diff --git a/KIV PPA2/Prednaska07.md b/KIV PPA2/Prednaska07.md new file mode 100644 index 0000000..a54240f --- /dev/null +++ b/KIV PPA2/Prednaska07.md @@ -0,0 +1,158 @@ +# Seznam + +- abstraktní datová struktura +- umožňuje vložení i odebrání prvku z jakékoliv pozice + +Jak specifikovat pozici? +- indexem +- aktuální pozice + +### Ukazovátko + +- ukazuje na aktuální pozici v seznamu +- posun dopředu i na začátek +- operace v $\Theta(1)$ +- **možné interpretace**: + - ukazuje na prvek + - některé operace problematické (např. vložení - před nebo za prvek?) + - ukazuje mezi prvky + - jednožnačné vkládání: sem + - vybírání/odebírání dohodou - třeba prvek napravo + +### Implementace spojovou strukturou + +- opět spojovací dílek - data a následující prvek +- reference na první (`first`) a aktuální prvek (`current`) +- ukazovátko míří na `current` a `current.next` +- je-li `current = null`, míří se před první prvek seznamu +- **pohyb ukazovátka**: + - `moveToFirst` - na začátek + - `next` - na další prvek + - potřeba myslet na posun z `null` a neexistující další prvek +- **přidávání** mezi dva prvky: + - přepíše se odkaz `current.next` na vložený prvek + - vloženému prvku se nastaví původní `current.next` +- **mazání** prvku + - vyřešení speciálních případů (na začátku, na konci) + - `current.next = current.next.next`, prvek se přeskočí +- **vybrání** prvku na zadané pozici + - projdeme seznam od začátku + - $\Omega(n)$ složitost! + +### Iterátor + +- seznam neumožňuje prácí **na více místech** +- vznik odděleného ukazovátka od dat - **iterátoru** (návrhový vzor) +- třída, která má aktuální index `current` a referenci `list +- stejná implementace jako u seznamu (místo `first` se použije `list.first`)` + +**Operace** +- vybrání dat napravo (`get()`) +- posunutí doprava (`next()`) +- vrácení na začátek (`moveToFirst()`) +- přidání prvku na pozici (`insert(...)`) +- odstranění prvku napravo (`remove()`) +- vytvoření klonu (`clone()`), který ukazuje na stejný prvek + +**Problémy** +- iterátory o sobě nevědí + - jeden smaže prvek, na který odkazuje jiný iterátor + - řešení + - používat více iterátorů pouze pro čtení + - při editaci zajistit, aby nebyl zasažen jiný iterátor +- pohyb pouze dopředu + - řešení: obousměrně zřetězený seznam + - spojovací prvek s `next` i `previous ` + - v iterátoru nová metoda `previous()` + - složitější konzistence struktury + - 2x více režijní paměti + +### Implementace paralelními poli + +- jen dopředné zřetězení +- dvě stejně dlouhá pole + - pro data + - pro index následovníka (`next`) - prázdného či obsazeného prvku +- index začátku `first` +- index volného pole `empty` +- index aktuálního prvku `current` + +# Kolekce v Javě + +Java poskytuje knihovní třídy pro základní implementaci kolekcí + +### Třída `LinkedList` + +- 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 iterator()` +- `ListIterator listIterator()` - lepší iterátor + +### Třída `ArrayList` + +- 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` + +**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`** +- 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` + +- rozhraní fronty +- `LinkedList` toto rozhraní implementuje + +**Operace** +- `void add()` +- `T element()` +- `T remove()` + +### Třída `Stack` + +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)$. \ No newline at end of file