Binární vyhledávací stromy
definice, užití a implementace, vyvažování, AVL stromy – princip algoritmu
Definice
Binární vyhledávací strom je datová struktura založená na binárním stromu, v němž jsou jednotlivé prvky uspořádány tak, aby v tomto stromu bylo možné rychle vyhledávat.
Binární strom
Jedná se o orientovaný graf s jedním vrcholem (kořen stromu), z něhož vede cesta ke všem ostatním vrcholům. Každý vrchol může mít maximálně dva potomky. Každý potomek může mít maximálně jednoho předka (s vyjimkou kořene, ten nemá žádného předka).
![]() |
---|
obr. 1: Binární strom |
Převzato z: https://cs.wikipedia.org/wiki/Bin%C3%A1rn%C3%AD_strom |
Implementace a vlastnosti vyhledávacích binárních stromů
- jedná se o binární strom (každý uzel má nejvýše dva potomky)
- každému uzlu je přiřazen určitý klíč (hodnota)
- levý podstrom každého uzlu obsahuje pouze menší hodnoty než je klíč tohoto uzlu
- pravý podstrom každého uzlu obsahuje pouze větší hodnoty než je klíč tohoto uzlu
Užití
- konstrukce a prohledávání asociativních polí (klíč - hodnota)
- průchod je pomalejší nežli hashovací tabulka, ale průchod stromem vydá seznam seřazených hodnot (hodí se na intervalové dotazy)
- slouží jako základ pro komplexnější vyhledávací datové struktury
Operace
Máme základní čtyři:
- vyhledávání
- vkládání
- mazání
- procházení stromu
Vyhledávání
Probíhá rekurzivně. Začínáme v kořenu stromu. Algoritmus porovná hledanou hodnotu s klíčem uzlu. Pokud se rovná, našli jsme hledanou hodnotu. Pokud je menší, jdeme doleva, pokud je větší, jdeme doprava. Toto se děje, dokud jsme nenalezli hodnotu, nebo nedorazili do listu stromu.
Časová složitost vyhledávání závisí na hloubce stromu. V průměrném případě má logaritmickou časovou složitost O(log n), ale pokud je strom nevyvážený a podobá se seznamu, může mít i lineární časovou složitost O(n). Otázka správného vyvážení je z tohoto pohledu kritická a řeší ji například AVL-strom.
Vkládání
Probíhá podobně jako vyhledávání, akorát hledanou hodnotou je hodnota vkládaného uzlu. Mohou nastat dva případy:
- strom již hodnotu obsahuje, není třeba ji vložit
- algoritmus narazil na neexistující uzel (například chce jít z uzlu doprava, ale žádný uzel tam není) -> našli jsme místo, kam uzel patří
Mazání
Zde může nastat několik případů:
- hledaným uzlem je list, ten můžeme klidně smazat
- hledaným uzlem je uzel s jedním potomkem -> smažeme uzel a nahradíme tento uzel potomkem
- hledaný uzlem je uzel se dvěma potomky -> hodnota uzlu je nahrazena nejbližší vyšší (nejlevější uzel pravého podstromu), nebo nižší hodnotou (nejpravější uzel levého podstromu)
Procházení stromu
Pouze procházíme strom, nijak ho neměníme, složitost odpovídá výšce stromu.
Řazení uzlů
Jedná se o proces zařazení hodnot stromu dle velikosti.
Vkládáme všechny hodnoty které chceme seřadit do vhodně uspořádané datové struktury -> binární strom. Následně stromem projdeme do hloubky a získáme seznam hodnot uspořádaný podle velikosti.
- nejhorší případ je n2 času, a to pokud se přidávají již seřazené hodnoty. Ty se totiž spojí do seznamu takže strom nemá levé větve.
Metody vkládání a mazání jsou často destruktivní -> tedy ničí vyváženost našeho stromu (to je takový strom, kde je rozdíl výšky podstromů uzlu menší než 2).
Jak vyvážíme strom?
AVL stromy
Jedná se o typ binárního vyhledávacího stromu. Konkrétně se jedná o samovyvažující se binární vyhledávací strom.
K vlastnostem binárních vyhledávacích stromů přidává AVL další vlastnost:
- délka nejdelší větve levého a pravého podstromu každého uzlu se liší nejvýše o 1, jinak strom není vyvážený
AVL strom definuje postupy zajišťující vyvážení stromu pro operace, jež mají šanci strom zdegenerovat:
- vkládání
- mazání
Vše je založeno na kritériu vyváženosti. Jedná se o číslo, které nám říká, jak se liší výška levého a pravého podstromu daného uzlu. Každý uzel má ideálně svoje kritérium vyváženosti, které pravidelně aktualizujeme.
Vkládání do AVL stromu
Stejné jako u binárního vyhledávacího stromu, až na to, že po vložení se aktualizují koeficienty vyváženosti uzlů, které byly na cestě směrem ke kořenu.
Není-li splněno kritérium vyváženosti, musíme provést vyvažování stromu pomocí cyklické záměny ukazatelů (rotace stromu).
- Při vkládání stačí vyvážit pouze první nalezený uzel, jehož koeficient vyváženosti je porušen, tím že ho opravíme, vyvážíme celý strom -> změna vyvolaná přidáním uzlu ovlivní pouze první nevyvážený uzel a jeho podstromy.
Mazání z AVL stromu
Stejné jako u binárního vyhledávacího stromu tím, že pokud dojde k porušení vyváženosti, provede se vyvážení. Na rozdíl od vyvažování při vkládání uzlů, při odebírání uzlů se musí projít celá cesta až do kořene stromu a opravit koeficienty vyvážení a případně provést rotace -> změna vyvolaná odstraněním může ovlivnit vyváženost celého podstromu kořene.
Vyvažování
Vyvážení docílíme tím, že vhodně zrotujeme celý podstrom, tak aby byla splněna vlastnost AVL stromů (Výška dvou podstromů se může lišit maximálně o 1)
-
rotací změníme pořadí uzlů ve stromu; máme dva druhy rotace:
- jednoduchá (rotujeme doleva, pokud je pravý podstrom vyšší; rotujeme doprava pokud je levý podstrom vyšší)
- složitá (rotujeme dvakrát pokaždé v opačném směru)
-
rotace probíhají vždy skrze uzel, jehož koeficient vyváženosti je narušen
-
rotace si můžeme představit jako řetěz, za který zatáhneme a levý/pravý podstrom posuneme
obr. 2: Příklad pravé rotace. T označuje podstromy, x a y jsou uzly. |
Převzato z: https://akela.mendelu.cz/~foltynek/TI/old/TI13%20Stromy.pdf |
Zdroje
- Binární vyhledávací strom. Wikipedie: Otevřená Encyklopedie. [online] @2023 [citováno: 17.05.2023]
Dostupné z: https://cs.wikipedia.org/wiki/Bin%C3%A1rn%C3%AD_vyhled%C3%A1vac%C3%AD_strom - Binární strom. Wikipedie: Otevřená Encyklopedie. [online] @2023 [citováno: 17.05.2023]
Dostupné z: https://cs.wikipedia.org/wiki/Bin%C3%A1rn%C3%AD_strom - Stromy. Mendelova univerzita v Brně. [online] @2023 [citováno: 17.05.2023]
Dostupné z: https://akela.mendelu.cz/~foltynek/TI/old/TI13%20Stromy.pdf - AVL-strom. Wikipedie: Otevřená Encyklopedie. [online] @2023 [citováno: 17.05.2023]
Dostupné z: https://cs.wikipedia.org/wiki/AVL-strom