Programování 4. 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 Stromy Reprezentace Binární vyhledávací stromy Create Find, Insert, Delete Vypis (inorder, preorder, postorder) Vyvážené stromy (stručně) Dokonale vyvážený binární vyhledávací strom AVL strom Jan Lánský Programování 4. hodina 2
Cíle hodiny Využití stromů při řešení praktických příkladů Načtení stromu z textového zápisů vztahů mezi daty Binární vyhledávací strom jako slovník Průchod obecným stromem do hloubky s využitím zásobníku Průchod obecným stromem do šířky s využitím fronty Vyhodnocení aritmetického výrazu Jan Lánský Programování 4. hodina 3
Rodokmen z textové podoby do podoby stromu Praktický příklad Textový soubor každý řádek reprezentuje otce a jeho potomky Otec: potomek,, potomek Označení osob musí být unikátní (v praxi jméno, příjmení, datum a místo narození) Chceme převést do podoby obecného stromu Txt soubor: pozor na umístění a počty mezer. Naše řešení je požaduje přesně. Pokud bude vstup vytvářet člověk, udělá chyby. Jan Lánský Programování 4. hodina 4
Rodokmen Jan Petr Pavel Pepa Lukas Jirka Ondra Adam Ales Filip Mirek Jan Lánský Programování 4. hodina 5
Myšlenka algoritmu Obecný strom, jehož kořen je otec z prvního řádku Projdeme soubor po řádcích. Rozpoznáme jméno otce a jeho synů Pokud se otec nevyskytuje ve stromu, chyba, končíme. V obecném stromu k otci přidáme jeho syny Pokud jména nejsou unikátní (chyba), přidáváme všechny syny prvnímu nalezenému jmenovci Jan Lánský Programování 4. hodina 6
Pomocný binární vyhledávací strom slovník V obecném stromu musíme projít všechny prvky, abychom nalezli hledaný uzel. Zrychlení: použijeme slovník (binární vyhledávací strom), který bude překládat jména osob na uzly obecného stromu Místo hledání v obecném stromu (lineární čas) budeme hledat v binárním vyhledávacím stromu (logaritmický čas) Stojí nás to dvojnásobek paměti Jan Lánský Programování 4. hodina 7
Datové struktury Místo celých čísel pracujeme s řetězci. Změní se těla funkcí Insert a Find Obecný strom: Jméno uzlu a pole synů Binární vyhledávací strom: Klíč: jméno uzlu Hodnota: uzel obecného stromu Levý: levý syn Pravý: pravý syn Jan Lánský Programování 4. hodina 8
Vytvoření uzlu Obecný strom: Vytvoříme pole pro dva syny Počet synů je nula. Binární vyhledávací strom: Známe z minulé hodiny Jan Lánský Programování 4. hodina 9
Přidání syna do obecného stromu Projdeme pole synů a hledáme prvek s hodnotou null. Pokud ho nalezneme, změníme ho na přidávaného syna a hodnotu null posuneme na další prvek Dynamické pole Bylo-li pole synů plné, zvětšíme ho na dvojnásobek. Do nového pole okopírujeme původní hodnoty, přidáme nový prvek, nastavíme zarážku null. Jan Lánský Programování 4. hodina 10
Oddělovač synů Pozor na mezery Otec končí před dvojtečkou Otec není ve slovníku. Buďto je to kořen, nebo chyba Pole řetězců se jmény synů Přidáme syna do slovníku Přidáme syna do obecného stromu Jan Lánský Programování 4. hodina 11
Průchod stromem AJ: Do hloubky: Deep first search (DFS) Do šířky: Breadth first search (BFS) Průchod do hloubky (DFS) - Backtracking Rekurze Zásobník prvky zásobníku jsou uzly stromu Průchod do šířky (BFS) - Vlna Fronta Prvky fronty jsou uzly stromu Přidáme datovou položku uzlu, zda byl navštíven nebo ne. Můžeme přidat i položku pro hloubku uzlu ve stromě. S uzly můžeme provést během průchodu požadovanou operaci (např. výpis hodnoty) Jan Lánský Programování 4. hodina 12
Průchod stromem do hloubky Preorder První je vypsán otec, pak synové Viz výstup nalevo od textu Inorder U binárních stromů: Pořadí výpisu je levý syn, otec, pravý syn. Postorder Nejprve jsou vypsání synové pak otec Jan Lánský Programování 4. hodina 13
Obecný strom nové položky Přidáme poznámku, zda jsme uzel už navštívili, nutné pro nerekurzivní průchody. Hloubka uzlu = vzdálenost od kořene v počtu uzlů Uzel je nenavštíveny při svém vzniku Uzel je kořen. Operace insert, delete nebudou měnit hloubku, zjistíme ji až při průchodu stromem Jan Lánský Programování 4. hodina 14
Pomocné funkce pro výpis Vypíše za každou úroveň hloubky hvězdičku a pak vypíše název uzlu. Vrátí dalšího nenavštíveného syna uzlu nebo null. Jan Lánský Programování 4. hodina 15
Preorder Minulou hodinu jsme použili na Binární vyhledávaci strom funkce Vypis Průchod do hloubky: rekurze Vypíšeme uzel a jeho hloubku Rekurzivní DFS stromem může projít syny v obyčejném cyklu, ale udělali jsme obecněji. Nastavíme mu hloubku uzlu a spostíme na něm rekurzi Další nenavštívený syn uzlu Start rekurze Jan Lánský Programování 4. hodina 16
Preorder Praktická ukázka bude na tabuli Průchod do hloubky: zásobník Dokud není zásobník prázdný Musí to být zásobník uzlů stromů Kořen stromu na zásobník Vyzvedneme vrchol zásobníku, Pokud nebyl navštíven, tak ho vypíšeme (a označíme navštívení). Otce bez synů dále nezpracováváme. Má-li uzel nenavštíveného syna, nastavíme synovi hloubku a otce i syna dáme na zásobník Jan Lánský Programování 4. hodina 17
Průchod stromem do šířky Uzly jsou vypisovány dle vzdálenosti od kořene Nejprve je vypsán kořen Poté synové kořene Poté vnuci kořene, Použití datové struktury Fronta Nevýhoda: z výpisu (nalevo) nepoznáme, kdo je čí otec Jan Lánský Programování 4. hodina 18
Praktická ukázka bude na tabuli Průchod do šířky: fronta Velmi podobné jako při použití zásobníku, pouze synové se přidávají do fronty najednou v cyklu Syny musíme označit za navštívené už při vložení do fronty, technické řešení kvůli funkci NextSon Jan Lánský Programování 4. hodina 19
Vyhodnocení aritmetického výrazu Praktická ukázka bude na tabuli Problém: lidé používají infixový zápis, který se musí pro optimální počítačové zpracování převést na prefixní zápis Infixní 2 + 3 * ( 7 + 2 ) 4 Prefixní: - + 2 * 3 + 7 2 4 Při uložení výrazu do stromu ho vyhodnotíme průchodem stromem do hloubky Uzly operace, listy čísla. Literatura Kučera: slajdy 93 99 Topfer: strany 63-70 Prefixní zápis nepotřebuje závorky Jan Lánský Programování 4. hodina 20
Zpětná vazba Objevili jste ve slajdech chyby? 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í 4. hodina 21