STROMY Datová struktura sestávající z uzlů Uzel – má jednoho předchůdce a N následníků Kořen – uzel, který nemá předchůdce List – uzel, který nemá následníky Pro N=2 hovoříme o binárních stromech
BINÁRNÍ STROMY Každý uzel má nejvýše dva potomky Jednoduchý , acyklický souvislý graf Hierarchická nelineární struktura Úplný BS – každý uzel má právě dva potomky, nebo je listem Úroveň k BS; každá úroveň má až 2k uzlů Vyvážený BS Binární vyhledávací strom
BINÁRNÍ STROM 0. úroveň 1. úroveň 2. úroveň 3. úroveň 4. úroveň KOREN nil nil nil 2. úroveň nil nil nil nil 3. úroveň nil nil nil 4. úroveň
USPOŘÁDANÝ STROM Často jsou stromy aplikovány v řadicích a vyhledávacích algoritmech Uspořádání uzlů je podle datových položek – klíče Uspořádání: Klíč (hodnota) každého uzlu je větší než hodnoty (klíče) všech uzlů jeho levého podstromu a menší než klíče všech uzlů jeho pravého podstromu – binární vyhledávací strom (BVS)
BINÁRNÍ STROM (s hodnotami) KOREN 10 0. úroveň 8 19 1. úroveň 2 nil 9 nil 16 20 nil 2. úroveň 4 nil 13 nil 18 nil 25 nil 3. úroveň 5 nil 12 nil 23 nil 4. úroveň
POUŽITÍ STROMŮ Hledání duplicitních výskytů Řazení pomocí binárního stromu Prohlížení stromu a tisk hodnot (klíčů) type SPOJ = ^UZEL UZEL = record HODN: byte {string[14],...} LU, PU: SPOJ end; var KOREN: SPOJ;
TVORBA BINÁRNÍHO STROMU procedure VLOZ(var KAM: SPOJ; CO: byte); begin if KAM = nil then begin new (KAM); KAM^.HODN := CO; KAM^.LU := nil; KAM^.PU := nil; end else if CO < KAM^.HODN then VLOZ(KAM^.LU, CO) {vlevo} else VLOZ(KAM^.PU, CO) {vpravo}
Vlastní strom vytvoříme např. algoritmem Procedure VYTVOR(var BS:SPOJ); var KAM:SPOJ; CO:byte; {nebo integer, string apod.} begin BS:=nil; Write(‘Napis koren: ’); Readln(CO); if CO<>0 then VLOZ(BS,CO); {konec pri CO=0} while CO<>0 do begin Write(‘Dalsi uzel: ‘); Readln(CO); if CO<>0 then begin KAM:=BS; VLOZ(KAM,CO) end
PRŮCHOD STROMEM V podstatě existují tři možnosti průchodů stromem: PREORDER navštiv kořen projdi levý podstrom PREORDER projdi pravý podstrom PREORDER
procedure PREORDER(H: SPOJ); begin if H <> nil then begin writeln(H^.HODN); PREORDER(H^.LU); PREORDER(H^.PU) end Uskuteční se postupně tisk uzlů: 10 8 2 4 5 9 19 16 13 12 18 20 25 23
INORDER projdi levý podstrom INORDER navštiv kořen projdi pravý podstrom INORDER
procedure INORDER(H: SPOJ); begin if H <> nil then begin INORDER(H^.LU); writeln(H^.HODN); INORDER(H^.PU) end Uskuteční se postupně tisk uzlů: 2 4 5 8 9 10 12 13 16 18 19 20 23 25 Tímto způsobem dostáváme vzestupně seřazené hodnoty. Vzájemnou výměnou obou příkazů procedury INORDER bychom tiskli hodnoty seřazené sestupně.
POSTORDER projdi levý podstrom POSTORDER projdi pravý podstrom POSTORDER navštiv kořen
procedure POSTORDER(H: SPOJ); begin if H <> nil then begin POSTORDER(H^.LU); POSTORDER(H^.PU); writeln(H^.HODN) end Uskuteční se postupně tisk uzlů: 5 4 2 9 8 12 13 18 16 23 25 20 19 10 Tento přístup využijeme při rušení stromů, postupně uvolňujeme (dispose) listy počínaje vždy nejlevějším listem.
Vypíšeme-li hodnoty z binárního stromu metodou (procedura) INORDER, získáme neklesající posloupnost hodnot: procedure TISK(PS: SPOJ); begin if PS <> nil then begin TISK(PS^.LU); writeln(PS^.HODN); TISK(PS^.PU) end
Procedura TISK je totožná s procedurou INORDER; spojíme-li však tisk hodnot s uvolněním příslušných uzlů, je pak zřejmé, že uvolňování uzlů provedeme metodou (procedurou) POSTORDER: procedure TISK(PS: SPOJ); begin if PS <> nil then begin TISK(PS^.LU); writeln(PS^.HODN); TISK(PS^.PU); dispose(PS) end
Reprezentace aritmetického výrazu binárním stromem Aritmetický výraz tvořený operandy a binárními operátory Kořen stromu obsahuje operátor, jeho levý či pravý podstrom tvoří buď výraz, který má opět levý a pravý podstrom operandy; operand je listem (nemá podstromy)
Reprezentace výrazu A+B*C Reprezentace výrazu (A+B)*C KOREN KOREN + * A nil * + C nil B nil C nil A nil B nil Reprezentace výrazu A+B*C Reprezentace výrazu (A+B)*C
Reprezentace výrazu (A+B*C)/((A+B)*C) KOREN / + * A nil * + C nil B nil C nil A nil B nil Reprezentace výrazu (A+B*C)/((A+B)*C)
Při průchodu jednotlivých stromů I)-III) metodou PREORDER navštěvujeme uzly v pořadí ad I) +A*BC ad II) *+ABC ad III) /+A*BC*+ABC Dostáváme tzv. prefixovou formu zápisu výrazu.
Při průchodu jednotlivých stromů I)-III) metodou POSTORDER navštěvujeme uzly v pořadí ad I) ABC*+ ad II) AB+C* ad III) ABC*+AB+C*/ Dostáváme tzv. postfixovou formu zápisu výrazu. Obě uvedené formy, zejména pak tato postfixová, (na rozdíl od infixové formy) se uplatňují např. při tvorbě analyzátorů jako součásti překladačů.
Při průchodu jednotlivých stromů I)-III) metodou INORDER navštěvujeme uzly v pořadí ad I) A+B*C ad II) A+B*C ad III) A+B*C/A+B*C Dostáváme vcelku nepoužitelnou (nejedno-značnou) infixovou formu zápisu výrazu. Infixová forma zápisu výrazu vyžaduje použití závorek k vyznačení priority prováděných operací