Programování 2. hodina RNDr. Jan Lánský, Ph.D. Katedra informatiky a matematiky Fakulta ekonomických studií Vysoká škola finanční a správní 2015
Umíme z minulé hodiny Obecné informace o předmětu Statická a dynamická alokace paměti Operátor new, struktura vs. třída Jednosměrné lineární spojové seznamy Create, ConvertArray, Print InsertToBegin, InsertToEnd InsertBefore, InsertAfter, Find, FindPrevious, Delete Jan Lánský Programování 2. hodina
Cíle hodiny Implementace zásobníku a fronty pomocí jednosměrných spojových seznamů Obousměrné lineární spojové seznamy Create, ConvertArray, Print InsertToBegin, InsertToEnd InsertBefore, InsertAfter, Find, Delete Cyklické spojové seznamy Jan Lánský Programování 2. hodina
Zásobník pomocí jednosměrného seznamu Třída Seznam – jednosměrný lineární spojový seznam prvků Třída Zasobnik – vrchol – začátek spojového seznamu Oproti implementaci pomocí pole Nepotřebujeme znát maximální počet prvků (v praxi obvykle toto omezení nebývá pro implementaci v poli zásadní – využití v backtrackingu) Může být pomalejší, kvůli dynamické alokaci Jan Lánský Programování 2. hodina
Zásobník – implementace I. Jednosměrný lineární spojový seznam Zásobník vrchol zásobníku – začátek seznamu Vytvoříme prázdný zásobník: vrchol je null Je zásobník prázdný ? Otestujeme zda vrchol je null Jan Lánský Programování 2. hodina
Zásobník – implementace II. Oproti struktuře není ref Nový prvek připojíme na začátek seznamu = vrchol zásobníku Vrátíme hodnotu prvku na začátku seznamu = vrcholu zásobníku Uložíme hodnotu prvku na začátku seznamu =vrcholu zásobníku Odstraníme vrchol zásobníku Jan Lánský Programování 2. hodina
Zásobník: grafické znázornění Push(3); Push(2); Push(1); vrchol data 1 2 3 next null Jednosměrný seznam Jan Lánský Programování 2. hodina
Fronta pomocí jednosměrného seznamu Třída Seznam – jednosměrný lineární spojový seznam prvků Třída Fronta zacatek – [odkaz na] začátek seznamu konec – [odkaz na] konec toho samého seznamu Oproti implementaci pomocí pole Nepotřebujeme znát maximální počet prvků (V praxi velká výhoda využití při vlně) Nemusíme se zabývat posunem nebo cyklčností Může být pomalejší, kvůli dynamické alokaci Jan Lánský Programování 2. hodina
Fronta – implementace Create – vytvoří prázdnou frontu Bude za úkol na cvičení Create – vytvoří prázdnou frontu Enqueue – vloží prvek na konec fronty Pozor na vkládání do prázdné fronty Dequeue – odebere prvek ze začátku fronty a vrátí jeho hodnotu Pozor na odebírání z jednoprvkové fronty Front – vrátí hodnotu prvku ze začátku fronty IsEmpty – zda je fronta prázdná Jan Lánský Programování 2. hodina
Fronta: grafické znázornění Enqueue(1); Enqueue(2); Enqueue(3); konec zacatek data 1 2 3 next null Jednosměrný seznam Jan Lánský Programování 2. hodina
Obousměrný lineární spojový seznam Lidově: obousměrný spoják AJ: Doubly linked list Datová struktura, který umožňuje uchovat dopředu neznámý počet prvků daného datového typu Tři datové položky: (data), [Odkaz na] další prvek (next) a [Odkaz na] předchozí prvek (prev) Začátek seznamu prev = null Konec seznamu next = null Vkládání a mazání prvků na libovolné místo vždy v čase O(1) Vyhledání prvku v čase O(n) Předchůdce a následník Jan Lánský Programování 2. hodina
Nelze říct, který seznam je lepší, záleží na konkrétním použití Spojové seznamy Jednosměrný Ukazatel next InsertAfter O(1) InsertBefore, Delete O(n) bez triku InsertBefore, Delete O(1) při znalosti předchůdce nebo trikem Obousměrný Ukazatelé next, prev Potřeba více paměti Insert, Delete O(1) Ale větší multiplikativní konstanta – více přepojování ukazatelů Nelze říct, který seznam je lepší, záleží na konkrétním použití Jan Lánský Programování 2. hodina
Obousměrný lineární spojový seznam Musí být class Seznam2 – odlišení od seznam Datová položka: libovolný datový typ i struktura Předchůdce prvku začátek seznamu: prev = null Následník prvku konec seznamu: next = null Vytvoříme 3 prvky … … s daty 1, 2, 3 Prvky napojíme za sebe 1,2,3 Prvky napojíme před sebe 1,2,3 První prvek -> poslední prvek -> první prvek Jan Lánský Programování 2. hodina
Grafické znázornění s1 s2 s3 data 1 2 3 prev null next s1.next s1.next.next.prev s1.next.next.prev.prev s1 s2 s3 data 1 2 3 prev null next s1.next.next Jan Lánský Programování 2. hodina
Práce s obousměrnými seznamy Zamyslet se, zda v dané funkci jsou tato ošetření třeba Při vytvářené, vkládání i mazání, je nutné upravovat [odkaz na] předchozí prvek i [odkaz na] následující prvek. Průchod obousměrným seznamem (Print, Find) je identický jako u jednosměrného. Platí všechna pravidla pro práci s jednosměrnými seznamy. Ošetřovat první a poslední prvek Návratová hodnota - prázdný seznam (null) Když se může změnit začátek seznamu funkce musí v návratové hodnotě vracet začátek seznamu Jan Lánský Programování 2. hodina
Create, ConvertArray Komentujeme jen rozdíly oproti jednosměrnému Předchůdce prvku nastavíme na null Předchůdcem nově vytvořeného prvku "tmp" bude prvek "akt", což je aktuální konec seznamu, který bude o prvek "tmp" prodloužen Jan Lánský Programování 2. hodina
InsertToBegin InsertToEnd Vložení hodnoty na začátek seznamu. Čas O(1) Vložení hodnoty na konec seznamu. Čas O(n) Předchůdcem původního začátku seznamu "s" se stane nově vkládaný prvek "tmp" Předchůdcem nově vkládaného prvku "tmp" se stane poslední prvek původního seznamu "akt", za který byl "tmp" připojen Jan Lánský Programování 2. hodina
InsertAfter Vložení hodnoty do seznamu za zadaný prvek "kam". Čas: O(1) 2) Jde i: kam.next.prev = tmp Pak není nutné vykonkat po (1) Krok (1) nutno před kroky (2) a (3) 1. Následníkem nově vytvořeného prvku "tmp" bude následník prvku "kam". 2. Pokud má prvek "tmp" následníka, stane se předchůdcem tohoto následníka prvek "tmp". 3. Následníkem prvku "kam" se stane prvek "tmp". 4. Předchůdcem prvku "tmp" se stane prvek "kam". Jan Lánský Programování 2. hodina
InsertAfter: grafické znázornění Vložení prvku s hodnotou 5 za prvek s hodnotou 2 tmp data 5 next prev s kam 1 2 3 null Krok 1 nutno před kroky 2 a 3 3) kam.next = tmp 4) tmp.prev = kam tmp.next = kam.next 2) tmp.next.prev = tmp Jan Lánský Programování 2. hodina
InsertBefore Vložení hodnoty do seznamu před zadaný prvek "kam". Čas: O(1) Podobné InsertAfter. Místo vkládání mezi kam a kam.next, vkládáme mezi kam.prev a kam Krok (1) nutno před krokem (3) 1. Předchůdcem nově vytvořeného prvku "tmp" bude předchůdce prvku "kam". 2. Následníkem předchůdce prvku "kam" se stane prvek "tmp" 3. Předchůdcem prvku "kam" se stane prvek "tmp". 4. Následníkem prvku "tmp" se stane prvek "kam". Jan Lánský Programování 2. hodina
Delete Smazání zadaného prvku. Čas: O(1) Při mazání prvního prvku musíme změnit začátek seznamu Pokud má mazaný prvek předchůdce, stane se následníkem tohoto předchůdce následník mazaného prvku. Pokud má mazaný prvek následníka, stane se předchůdcem tohoto následníka předchůdce mazaného prvku. Jan Lánský Programování 2. hodina
Delete: grafické znázornění Mažeme prvek "co" s hodnotou 2 co co.prev.next co.next.prev s co.prev co.next data 1 2 3 next null prev Jan Lánský Programování 2. hodina
Ukázka Delete a Insert mohou modifikovat začátek seznamu, nutno ukládat návratové hodnoty … 9, 11, 8 … … 9, 14, 11, … … 6, 15 5, 4, … 4, … Jan Lánský Programování 2. hodina
Cyklické spojové seznamy Kdy vymyslí praktický příklad využití ? Po posledním prvku seznamu následuje první prvek Seznam nemá začátek ani konec Při průchodu seznamem nutno hlídat, zda jsme ho prošli jen jednou if ((akt = akt.next) == s) break; Lze jednosměrné i obousměrné Jan Lánský Programování 2. hodina
Cyklický obousměrný seznam s.next.next.next s.prev.prev.prev s.next s.prev.prev s.next.next s.prev data 1 2 3 next prev Jan Lánský Programování 2. hodina
Zpětná vazba Objevili jste ve slajdech chyby? Nechápete nějaký slajd? Včetně pravopisných Nechápete nějaký slajd? Je příliš obtížný, nesrozumitelný? Máte nějaký nápad na vylepšení? Anonymní formulář Odeslání za pár vteřin http://goo.gl/forms/wJX99cbyy9 Jan Lánský Programování 2. hodina