# 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 **Operace** - přidání na konec - vybrání prvku na konci - odebrání prvku z konce **LIFO fronta** - last in, first out ### Implementace polem **Složitost operací** - vybrání prvku $\Theta(1)$ - odebrání prvku $\Theta(1)$, pokud se pole nezmenšuje - přidávání prvku - vejde-li se $\Theta(1)$ - nevejde-li se $\Theta(n)$ - pole 2x zvětšíme - v průměru? **Amortizovaná složitost** - zkoumáme přidání n prvků, pro jednoduchost je původní velikost pole 1 - kolikrát se pole zvětšuje? (záleží na n) - $n \leq 1$: 0x - $n \leq 2$: 1x - $n \leq 4$: 2x - $n \leq 2^k$: kx - počet zvětšování $k = \log_{2}n$ - počet kopírovaných prvků pro i-té zvětšení: $2^{i-1}$ - celkový počet operací při zvětšování: $\sum^{\log_{2}n}_{i=1} 2^{i-1}$ | počet prvků n | počet zvětšení | počet kopírovaných prvků | | ------------- | -------------- | ------------------------ | | $n \leq 1$ | 0x | 0 | | $n \leq 2$ | 1x | 1 | | $n \leq 4$ | 2x | 3 | | $n \leq 8$ | 3x | 7 | | $n \leq 16$ | 4x | 15 | | $n \leq 2^k$ | kx | $2^k - 1$ | - nejhorší případ: hned po zvětšení pole - $n = 2^k + 1, o = 2^{k+1} - 1$ - $o = 2(2k) - 1 = 2(2k + 1) - 3 = 2n - 3 < 2n$ - **závěr**: - složitost oprace přidání je $\mathcal{O}(n)$ - průměrná složitost je $\Theta(1)$ - při zvětšování **o konstantu** to neplatí - přidání n prvků $\Omega(n^2)$ - přidání jednoho prvku $\Omega(n)$ ### Implementace spojovým seznamem **Řešení** - vyrobíme si spojovací prvek - funguje podobně jako lego - připojuje se na něj jeden kousek dat - může se na něj připojit další spojovací prvek - **výhoda**: alokujeme místo na haldě po malých částech (pro každý přidávaný prvek) - **cena**: bude potřeba paměť navíc pro spojovací prvky **Složitost operací** - vybrání prvku $\Theta(1)$ - odebrání prvku $\Theta(1)$ - přidávání prvku $\Theta(1)$ + neumožňuje vybrat prvek na libovolném indexu v konstantním čase ### Kterou implementaci použít? Jak velké jsou položky v seznamu? - jsou-li malé, bude lepší implementace polem, kvůli šetření paměti - je to ale praktický problém? Potřebujeme zaručenou rychlost pro přidávání prvku? - při implementaci polem to může nějakou dobu trvat Tyto aspekty není potřeba se učit, vyplývají ze způsobu implementace. #### Použití z klientské třídy - použití obou implementací je úplně stejné - uživatel vůbec nemusí vědět, co se děje uvnitř - vnitřní data jsou udržována v konzistentním stavu Objektové programování - skrývání implementace - uživatel zná jen signaturu metod