Dynamické datové struktury I. Seznam. Fronta. Zásobník. Tomáš Bayer bayertom@natur.cuni.cz Katedra aplikované geoinformatiky a kartografie, Přírodovědecká fakulta UK. Tomáš Bayer bayertom@natur.cuni.cz (Katedra aplikované Dynamické geoinformatiky datové struktury a kartografie, I. Přírodovědecká fakulta UK.) 1 / 37
Obsah přednášky 1 Přehled dynamických datových struktur 2 Seznam 3 Zásobník 4 Fronta Tomáš Bayer bayertom@natur.cuni.cz (Katedra aplikované Dynamické geoinformatiky datové struktury a kartografie, I. Přírodovědecká fakulta UK.) 2 / 37
Přehled dynamických datových struktur 1. Odvozené datové struktury Nazývány také dynamickými datovými strukturami. Reprezentace tabulek, seznamů, grafů, matic, stromů. Používány při řešení řady typů informatických problémů: rychlé třídění, rychlé vyhledávání, překlady výrazů, kompresní algoritmy, optimalizační úlohy, počítačová grafika. Přehled dynamických datových struktur: Seznam (LIST) Zásobník (STACK) Fronta (QUEUE) Prioritní fronta (PRIORITY QUEUE) Strom (TREE) Tabulka (TABLE) Tomáš Bayer bayertom@natur.cuni.cz (Katedra aplikované Dynamické geoinformatiky datové struktury a kartografie, I. Přírodovědecká fakulta UK.) 3 / 37
Seznam 2. Seznam Datová struktura, tvoří ji neuspořádaná/uspořádaná posloupnost položek. Každá položka obsahuje odkaz na následující/předchozí položku. Patří mezi rekurzivní struktury, odkaz na položku stejného typu. Vlastnost seznamu: Rychlé přidávání prvků na počátek/konec seznamu (O(1)). Vhodný pro procházení prvků sekvenčně. Nevhodný pro přímý přístup k prvkům. Typy seznamů: jednosměrný seznam, obousměrný seznam, kruhový seznam. Tomáš Bayer bayertom@natur.cuni.cz (Katedra aplikované Dynamické geoinformatiky datové struktury a kartografie, I. Přírodovědecká fakulta UK.) 4 / 37
Seznam 3. Základní pojmy Implementace: Prostřednictvím pole. Zřetězený seznam. Procházení seznamem: Procházením jedním směrem: jednosměrný seznam. Procházení oběma směry: obousměrný seznam. Hlava seznamu, ohon: Head: první prvek seznamu. Tail: poslední prvek v seznamu. Odkaz na prvek: Ukazuje na následující / předchozí prvek seznamu. Optimalizace: Volba algoritmu + volba vhodné dynamické struktury! Tomáš Bayer bayertom@natur.cuni.cz (Katedra aplikované Dynamické geoinformatiky datové struktury a kartografie, I. Přírodovědecká fakulta UK.) 5 / 37
Seznam 4. Ukázky seznamů. Jednosměrný seznam: každý prvek seznamu odkazuje na předchozí resp. následující prvek seznamu. První resp. poslední prvek seznamu neodkazuje nikam (NULL). Obousměrný seznam: každý prvek seznamu obsahuje odkaz na předchozí a následující prvek seznamu. První a poslední prvek seznamu neodkazují nikam (NULL). Kruhový seznam: jednosměrný i obousměrný. Poslední prvek seznamu pak obsahuje odkaz na první prvek seznamu, resp. první prvek seznamu obsahuje odkaz na poslední prvek seznamu. Tomáš Bayer bayertom@natur.cuni.cz (Katedra aplikované Dynamické geoinformatiky datové struktury a kartografie, I. Přírodovědecká fakulta UK.) 6 / 37
Seznam 5. Operace se seznamem Základní operace se seznamem: Přidání prvku na konec seznamu (PUSH): O(1). Přidání prvku za daný prvek (INSERT): 0(1) + nalezení O(N). Nalezení prvku (FIND): O(N). Smazání prvku (DELETE): O(1). Smazání seznamu (CLEAR): O(N). Vhodný při čtení/přidávání prvků na začátku/ konci seznamu. Nevhodný pro přímý přístup. Podpora pouze sekvenčního přístupu. Tomáš Bayer bayertom@natur.cuni.cz (Katedra aplikované Dynamické geoinformatiky datové struktury a kartografie, I. Přírodovědecká fakulta UK.) 7 / 37
Seznam 6. Jednosměrný seznam, ukázka Třída Uzel.java Datová položka typu String: data. Datová položka typu Uzel: odkaz na další uzel. public class Uzel { String data; //Data Uzel dalsi; //Dalsi uzel public Uzel (String data_) //Konstruktor { data=data_; dalsi=null; //Neukazuje nikam Tomáš Bayer bayertom@natur.cuni.cz (Katedra aplikované Dynamické geoinformatiky datové struktury a kartografie, I. Přírodovědecká fakulta UK.) 8 / 37
Seznam 7. Vytvoření prázdného seznamu Postup vytvoření prázdného seznamu: 1 Vytvoření odkazu na počáteční a koncový uzel seznamu: prvni, posledni. 2 Inicializace obou odkazů na null. public class Seznam { private Uzel prvni; //Hlava private Uzel posledni; //Posledni prvek public Seznam(){ prvni=null; posledni=null; // Inicializace Tomáš Bayer bayertom@natur.cuni.cz (Katedra aplikované Dynamické geoinformatiky datové struktury a kartografie, I. Přírodovědecká fakulta UK.) 9 / 37
Seznam 8. Přidání prvku na konec seznamu Složitost operace O(1), přidání na jiné místo O(N). Postup přidání prvku na konec seznamu: 1 Alokace nového uzlu u. 2 Nastavení parametrů uzlu: Prázdný seznam. První a poslední uzel seznamu = u. Neprázdný seznam: Adresu přidávaného uzlu u uložena do položky dalsi. Uzel u se stává posledním uzlem. Tomáš Bayer bayertom@natur.cuni.cz (Katedra aplikované Dynamické geoinformatiky datové struktury a kartografie, I. Přírodovědecká fakulta UK.) 10 / 37
Seznam 9. Přidání prvku na konec seznamu, ukázka. Třída Seznam.java public void pridej(string data){ Uzel u=new Uzel(data); //Vytvoreni nove polozky if (posledni==null) { //Prazdny seznam prvni=u; posledni=u; else{ //Neprazdny seznam posledni.dalsi=u; //Adresa pridavaneho uzlu posledni=u; //uzel u koncovym uzlem Tomáš Bayer bayertom@natur.cuni.cz (Katedra aplikované Dynamické geoinformatiky datové struktury a kartografie, I. Přírodovědecká fakulta UK.) 11 / 37
Seznam 10. Výpis jednosměrného seznamu Prováděn v zadaném směru od prvního uzlu k poslednímu uzlu. Postup výpisu prvků: 1 Získání prvního uzlu u (hlava). 2 Pokud p!=null: výpis hodnoty aktuálního uzlu p. inkrementace uzlu p=p.dalsi. public void vypis() { Uzel p=prvni; //Nalezeni prvniho uzlu while(p!=null) { System.out.println(p.data); //Vypis polozky p=p.dalsi; //Dalsi uzel Tomáš Bayer bayertom@natur.cuni.cz (Katedra aplikované Dynamické geoinformatiky datové struktury a kartografie, I. Přírodovědecká fakulta UK.) 12 / 37
Seznam 11. Výpis jednosměrného seznamu, ukázka Třída Seznam.java public static void main (String [] args) { Seznam s=new Seznam(); s.pridej("pondeli"); s.vypis(); s.pridej("utery"); s.vypis(); s.pridej("streda"); s.vypis(); s.pridej("ctvrtek"); s.vypis(); Výsledek posledního výpisu: 1. Pondeli, 2. Pondeli, Utery, 3. Pondeli, Utery, Streda 4. Pondeli, Utery, Streda, Ctvrtek Tomáš Bayer bayertom@natur.cuni.cz (Katedra aplikované Dynamické geoinformatiky datové struktury a kartografie, I. Přírodovědecká fakulta UK.) 13 / 37
Seznam 12. Nalezení prvku v jednosměrném seznamu Prohledávání prováděno v zadaném směru od prvního uzlu k poslednímu. Postup nalezení prvku: 1 Hledaná hodnota h. 2 Získání prvního uzlu p seznamu (hlava). 3 Pokud p!=null: Pokud p.data == data vrat p. Jinak inkrementace p. 4 Hodnota h není v seznamu, vrat null. Tomáš Bayer bayertom@natur.cuni.cz (Katedra aplikované Dynamické geoinformatiky datové struktury a kartografie, I. Přírodovědecká fakulta UK.) 14 / 37
Seznam 13. Nalezení prvku v jednosměrném seznamu, ukázka Třída Seznam.java public Uzel najdi(string data) { Uzel p = prvni; while(p!= null) { if (p.data == data) { return p; p = p.dalsi; return null; Tomáš Bayer bayertom@natur.cuni.cz (Katedra aplikované Dynamické geoinformatiky datové struktury a kartografie, I. Přírodovědecká fakulta UK.) 15 / 37
Seznam 14. Přidání prvku za daný prvek Složitost operace O(1), avšak hledání uzlu, za který přidáváme O(N). Nutno sekvenčně projít předcházejících n 1 prvků. Postup přidání uzlu v za uzel u: 1 Alokace nového uzlu v. 2 Zařazení uzlu: Propojení uzlu v s následníkem u v.dalsi = u.dalsi; Propojení uzlu u s uzlem v u.dalsi = v; public void vloz(uzel u, String data) { Uzel v = new Uzel(data); //Vytvoreni noveho uzlu v.dalsi = u.dalsi; //Nastaveni naslednika v u.dalsi = v; //Nastaveni naslednika u Tomáš Bayer bayertom@natur.cuni.cz (Katedra aplikované Dynamické geoinformatiky datové struktury a kartografie, I. Přírodovědecká fakulta UK.) 16 / 37
Seznam 15. Smazání prvku v jednosměrném seznamu Vymazání prvku zadaného adresou ze seznamu. Problém: neznáme prvek předcházející hledanému prvku. Do mazaného prvku zkopírujeme obsah následujícího prvku (2 stejné prvky). Smažeme prvek za mazaným prvkem. Postup smazání prvku: 1 Přiřazení obsahu p.data = p.dalsi.data. 2 Smazání prvku p.dalsi ve 3 krocích: Pomocný uzel q = p.dalsi. Nastavení následníka: p.dalsi = p.dalsi.dalsi. Smazání uzlu q. Fáze 1: p=p.dalsi. Dva stejné prvky za sebou v seznamu. Tomáš Bayer bayertom@natur.cuni.cz (Katedra aplikované Dynamické geoinformatiky datové struktury a kartografie, I. Přírodovědecká fakulta UK.) 17 / 37
Seznam 16. Smazání prvku v jednosměrném seznamu Fáze 2: Nastavení následníka mazaného prvku na jeho následníka. Fáze 3: Smazání druhého z dvojice stejných prvků. Tomáš Bayer bayertom@natur.cuni.cz (Katedra aplikované Dynamické geoinformatiky datové struktury a kartografie, I. Přírodovědecká fakulta UK.) 18 / 37
Seznam 17. Smazání prvku v jednosměrném seznamu, ukázka Seznam.java public void smaz(uzel p) { p.data = (p.dalsi).data; //Kopie datove polozky Uzel q = p.dalsi; //Zapamatovani smazaneho uzlu p.dalsi = (p.dalsi).dalsi; //Nastaveni naslednika nasled q = null; Tomáš Bayer bayertom@natur.cuni.cz (Katedra aplikované Dynamické geoinformatiky datové struktury a kartografie, I. Přírodovědecká fakulta UK.) 19 / 37
Zásobník 18. Zásobník Princip zásobníku: Ze zásobníku odebíráme data v opačném pořadí, než v jakém jsme je do něj uložili. Pracovat lze pouze s prvkem, který je na vrcholu zásobníku. Reprezentuje model LIFO (Last In - First Out). V běžném životě model zásobníku např. batoh, vyndaváme z něj věci v opačném pořadí, než je do něj ukládáme. Použití při zpracovávání dat v sekvenčním pořadí. Implementování zásobníku: Spojovým seznamem. Polem. Složitost operací O(1). Tomáš Bayer bayertom@natur.cuni.cz (Katedra aplikované Dynamické geoinformatiky datové struktury a kartografie, I. Přírodovědecká fakulta UK.) 20 / 37
Zásobník 19. Základní pojmy a operace se zásobníkem Dno zásobníku: Nejspodnější prvek v zásobníku. Přidán do zásobníku jako první. Vrchol zásobníku: Nejvrchnější prvek v zásobníku. Přidán do zásobníku jako poslední. Operace se zásobníkem: Vytvoření zásobníku. Přidání prvku do zásobníku (PUSH). Odebrání prvku ze zásobníku (POP). Tomáš Bayer bayertom@natur.cuni.cz (Katedra aplikované Dynamické geoinformatiky datové struktury a kartografie, I. Přírodovědecká fakulta UK.) 21 / 37
Zásobník 20. Implementace zásobníku, třída Uzel Implementace zásobníku s použitím obousměrného lineárního seznamu. Každá položka seznamu obsahuje odkaz na předchozí položku seznamu a následující položku seznamu. Třída Uzel.java public class Uzel { String data; Uzel predchozi; //Predchozi uzel Uzel dalsi; //Nasledujici uzel public Uzel(String data_) { data=data_; predchozi=null; //Nastaveni predchudce dalsi=null; //Nastaveni naslednika Tomáš Bayer bayertom@natur.cuni.cz (Katedra aplikované Dynamické geoinformatiky datové struktury a kartografie, I. Přírodovědecká fakulta UK.) 22 / 37
Zásobník 21. Vytvoření prázdného zásobníku, ukázka Postup vytvoření prázného zásobníku: 1 Vytvoření odkazu na počáteční a koncový uzel seznamu: prvni, posledni. 2 Inicializace obou odkazů na null. public class Zasobnik { private Uzel prvni; //Prvni uzel zasobniku private Uzel posledni; //Posledni uzel zasobniku public Zasobnik() { //Konstruktor prvni=null; //Inicializace prvniho uzlu posledni=null; //Inicializace posledniho uzlu Tomáš Bayer bayertom@natur.cuni.cz (Katedra aplikované Dynamické geoinformatiky datové struktury a kartografie, I. Přírodovědecká fakulta UK.) 23 / 37
Zásobník 22. Přidání uzlu do zásobníku: PUSH Princip přidání uzlu do zásobníku: Přidávaný uzel je umist ován vždy na konec zásobníku. Je to efektivnější varianta než jeho přidání na počátek. Nutno nastavit přidávaný uzel jako následníka posledního uzlu a tomuto uzlu nastavit předchůdce. Postup přidání uzlu do zásobníku: 1 Vytvoření nového uzlu u. 2 Nastavení parametrů uzlu u: Prázdný seznam: První a poslední uzel seznamu tvoří uzel u. Neprázdný seznam (3 kroky): Adresu přidávaného uzlu u uložena do položky dalsi: posledni.dalsi = u Nastavení u.predchozi = posledni. Uzel u se stává posledním uzlem: posledni = u. Tomáš Bayer bayertom@natur.cuni.cz (Katedra aplikované Dynamické geoinformatiky datové struktury a kartografie, I. Přírodovědecká fakulta UK.) 24 / 37
Zásobník 23. Přidání uzlu do zásobníku, ukázka Zasobnik.java public void push(string data){ Uzel u=new Uzel(data); if(posledni==null) { prvni=u; posledni=u; else { posledni.dalsi=u; //Nastaveni dalsiho uzlu u.predchozi=posledni; //Nastaveni predchoziho uzlu posledni=u; //Nastaveni posledniho uzlu Tomáš Bayer bayertom@natur.cuni.cz (Katedra aplikované Dynamické geoinformatiky datové struktury a kartografie, I. Přírodovědecká fakulta UK.) 25 / 37
Zásobník 24. Vyjmutí uzlu ze zásobníku Princip vyjmutí uzlu do zásobníku: Ze zásobníku vždy vyjímán poslední uzel. Nutno nastavit nový konec fronty a jeho následníka nasměrovat na null. Postup vyjmutí uzlu ze zásobníku: 1 Zapamatování posledního uzlu: p = posledni 2 Pokud zásobník tvořen jedním prvkem (posledni.predchozi = null), pak prvni = null, posledni = null. 3 Pokud zásobník není prázdný (3 kroky): Nastavení posledního uzlu: posledni = posledni.predchozi Nastavení následníka: posledni.dalsi = null Smazání uzlu p:, p = null Tomáš Bayer bayertom@natur.cuni.cz (Katedra aplikované Dynamické geoinformatiky datové struktury a kartografie, I. Přírodovědecká fakulta UK.) 26 / 37
Zásobník 25. Vyjmutí uzlu ze zásobníku, ukázka Zasobnik.java public void pop() { Uzel p = posledni; if (posledni.predchozi == null) { //Pouze jeden prvek v z prvni = null; posledni = null; else { //Vice nez jeden prvek v zasobniku posledni = p.predchozi; //Nastaveni posledniho uzlu posledni.dalsi = null; //Nastaveni naslednika p = null; //Vymazani prvku Tomáš Bayer bayertom@natur.cuni.cz (Katedra aplikované Dynamické geoinformatiky datové struktury a kartografie, I. Přírodovědecká fakulta UK.) 27 / 37
Zásobník 26. Ukázka výpisu obsahu zásobníku Zasobnik z=new Zasobnik(); z.push("pondeli"); z.vypis(); z.push("utery"); z.vypis(); z.push("streda"); z.vypis(); z.push("ctvrtek"); z.vypis(); z.pop(); z.vypis(); Výsledek posledního výpisu: Pondeli, Utery, Streda Tomáš Bayer bayertom@natur.cuni.cz (Katedra aplikované Dynamické geoinformatiky datové struktury a kartografie, I. Přírodovědecká fakulta UK.) 28 / 37
Fronta 27. Fronta Z fronty odebíráme data ve stejném pořadí, v jakém jsem je do ní uložili. Pracovat lze pouze s prvkem, který je na čele fronty. Reprezentuje model FIFO (First In-First Out). Využití při sekvenčním zpracování dat. Ve frontě nemůžeme předbíhat. Existuje i fronta s předbíháním, tzv. prioritní fronta. Implementace fronty: Polem. Spojovým seznamem. Složitost operací O(1). Tomáš Bayer bayertom@natur.cuni.cz (Katedra aplikované Dynamické geoinformatiky datové struktury a kartografie, I. Přírodovědecká fakulta UK.) 29 / 37
Fronta 28. Základní pojmy a operace s frontou Konec fronty: Prvek na poslední pozici ve frontě. Do fronty frony přidán jako poslední. Čelo fronty: Prvek na první pozici ve frontě, Do fronty přidán jako první. Operace s frontou: Vytvoření fronty. Přidání prvku do fronty (PUSH). Odebrání prvku z fronty (POP). Tomáš Bayer bayertom@natur.cuni.cz (Katedra aplikované Dynamické geoinformatiky datové struktury a kartografie, I. Přírodovědecká fakulta UK.) 30 / 37
Fronta 29. Implementace fronty-třída Uzel, ukázka Implementace fronty s použitím obousměrného lineárního seznamu. Každá položka seznamu obsahuje odkaz na předchozí položku seznamu a následující položku seznamu (stejné jako u zásobníku). public class Uzel { String data; Uzel predchozi; //Predchozi uzel Uzel dalsi; //Nasledujici uzel public Uzel(String data_) //Konstruktor { data = data_; predchozi = null; dalsi = null; Tomáš Bayer bayertom@natur.cuni.cz (Katedra aplikované Dynamické geoinformatiky datové struktury a kartografie, I. Přírodovědecká fakulta UK.) 31 / 37
Fronta 30. Vytvoření prázdné fronty, ukázka Postup vytvoření prázdné fronty (analogie zásobníku): 1 Vytvoření odkazu na počáteční a koncový uzel seznamu: prvni, posledni. 2 Inicializace obou odkazů na null. public class Fronta { private Uzel prvni; private Uzel posledni; public Fronta() { prvni=null; posledni=null; Tomáš Bayer bayertom@natur.cuni.cz (Katedra aplikované Dynamické geoinformatiky datové struktury a kartografie, I. Přírodovědecká fakulta UK.) 32 / 37
Fronta 31. Přidání uzlu do fronty: PUSH Přidávaný uzel je umist ován vždy na konec zásobníku. Nutno nastavit přidávaný uzel jako následníka posledního uzlu a tomuto uzlu nastavit předchůdce. Postup stejný jako u zásobníku: 1 Alokace nového uzlu u. 2 Nastavení parametrů uzlu: Prázdný seznam: První a poslední uzel seznamu =u Neprázdný seznam: 1 Adresu přidávaného uzlu u uložena do položky dalsi: posledni.dalsi = u 2 Nastavení u.predchozi = posledni. 3 Uzel u se stává posledním uzlem: posledni = u. Tomáš Bayer bayertom@natur.cuni.cz (Katedra aplikované Dynamické geoinformatiky datové struktury a kartografie, I. Přírodovědecká fakulta UK.) 33 / 37
Fronta 32. Přidání uzlu do fronty: PUSH, ukázka Fronta.java public void push (String data){ Uzel u = new Uzel(data); if (posledni == null) { //Prazdna fronta prvni = u; posledni = u; else { //Neprazdna fronta posledni.dalsi = u; //Nastaveni dalsiho uzlu u.predchozi = posledni; //Nastaveni predchoziho uzl posledni = u; //Nastaveni posledniho uzlu Tomáš Bayer bayertom@natur.cuni.cz (Katedra aplikované Dynamické geoinformatiky datové struktury a kartografie, I. Přírodovědecká fakulta UK.) 34 / 37
Fronta 33. Vyjmutí uzlu z fronty: POP Princip vyjmutí uzlu z fronty: Z fronty vždy vyjímán první uzel. Nutno nastavit nový počáteční uzel fronty a jeho předchůdce. Postup vyjmutí uzlu z fronty: 1 Přiřazení p = prvni 2 Pokud je fronta tvořená jedním prvkem (prvni.dalsi = null), pak prvni = null, posledni = null. 3 Pokud fronta není prázdná (3 kroky): Nastavení prvního uzlu: prvni = prvni.dalsi Nastavení předchůdce: prvni.predchozi = null Smazání uzlu p: p = null Tomáš Bayer bayertom@natur.cuni.cz (Katedra aplikované Dynamické geoinformatiky datové struktury a kartografie, I. Přírodovědecká fakulta UK.) 35 / 37
Fronta 34. Vyjmutí prvku z fronty: POP, ukázka Fronta.java public void pop() { Uzel p = prvni; if (prvni.dalsi == null) { //Pouze jeden prvek prvni = null; posledni = null; else { //Neprazdna fronta prvni = prvni.dalsi; //Nastaveni prvniho uzlu prvni.predchozi = null; //Nastaveni predchudce p = null; //Smazani uzlu Tomáš Bayer bayertom@natur.cuni.cz (Katedra aplikované Dynamické geoinformatiky datové struktury a kartografie, I. Přírodovědecká fakulta UK.) 36 / 37
Fronta 35. Ukázka výpisu obsahu fronty Fronta.java Fronta f=new Fronta(); f.push("pondeli"); f.vypis(); f.push("utery"); f.vypis(); f.push("streda"); f.vypis(); f.push("ctvrtek"); f.vypis(); f.pop(); f.vypis(); Výsledek posledního výpisu: Utery, Streda, Ctvrtek Tomáš Bayer bayertom@natur.cuni.cz (Katedra aplikované Dynamické geoinformatiky datové struktury a kartografie, I. Přírodovědecká fakulta UK.) 37 / 37