230 likes | 542 Views
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
E N D
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 KOREN 0. úroveň 1. úroveň 2. úroveň 3. úroveň 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 0. úroveň 1. úroveň 2. úroveň 3. úroveň 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} end
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 end 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 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 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 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 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 <> nilthen begin TISK(PS^.LU); writeln(PS^.HODN); TISK(PS^.PU); dispose(PS) end 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 * *
KOREN • 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í