1. Vyhledávací stromy



Podobné dokumenty
1. Vyhledávací stromy

1. Vyhledávací stromy

1. Vyhledávací stromy

Vyvažování a rotace v BVS, všude se předpokládá AVL strom

Programování 3. hodina. RNDr. Jan Lánský, Ph.D. Katedra informatiky a matematiky Fakulta ekonomických studií Vysoká škola finanční a správní 2015

bin arn ı vyhled av an ı a bst Karel Hor ak, Petr Ryˇsav y 23. bˇrezna 2016 Katedra poˇ c ıtaˇ c u, FEL, ˇ CVUT

Padovan heaps Vladan Majerech

Amortizovaná složitost. Prioritní fronty, haldy (binární, d- regulární, binomiální, Fibonacciho), operace nad nimi a jejich složitost

Diferencovatelné funkce

AVL stromy. pro každý uzel u stromu platí, že rozdíl mezi výškou jeho levého a pravého podstromu je nejvýše 1 stromy jsou samovyvažující

Stromy, haldy, prioritní fronty

Stromy. Jan Hnilica Počítačové modelování 14

1 Linearní prostory nad komplexními čísly

ADT STROM Lukáš Foldýna

Binární vyhledávací stromy pokročilé partie

PQ-stromy a rozpoznávání intervalových grafů v lineárním čase

V každém kroku se a + b zmenší o min(a, b), tedy vždy alespoň o 1. Jestliže jsme na začátku dostali 2

( ) Opakování vlastností funkcí. Předpoklady:

Binární vyhledávací stromy

kopci a tuto představu přetavit do náčrtku celé situace, viz. obr.1. Aby však tento náčrt nebyl

Binární vyhledávací strom pomocí směrníků Miroslav Hostaša L06620

autoři: Rudolf Bayer, Ed McCreight všechny vnější uzly (listy) mají stejnou hloubku ADS (abstraktní datové struktury)

zejména Dijkstrův algoritmus pro hledání minimální cesty a hladový algoritmus pro hledání minimální kostry.

Adresní vyhledávání (přímý přístup, zřetězené a otevřené rozptylování, rozptylovací funkce)

Binární Vyhledávací Stromy, u kterých je. složitost operací v nejhorším. rovná O(log n)

Ukážeme si lineární algoritmus, který pro pevné k rozhodne, zda vstupní. stromový rozklad. Poznamenejme, že je-li k součástí vstupu, pak rozhodnout

Algoritmy a datové struktury

1. Minimální kostry Od mìsteèka ke kostøe

Výroková a predikátová logika - II

1. Binomiální haldy Zavedení binomiální haldy

Vyhledávací stromy. Slouží jako pomůcka pro organizaci dat umožňující efektivní vyhledávání.

Algoritmizace Dynamické programování. Jiří Vyskočil, Marko Genyg-Berezovskyj 2010

SOUSTAVY LINEÁRNÍCH ALGEBRAICKÝCH ROVNIC

+ 2y. a y = 1 x 2. du x = nxn 1 f(u) 2x n 3 yf (u)

Riemannův určitý integrál

a) b) c) Radek Mařík

Dijkstrův algoritmus

[ 5;4 ]. V intervalu 1;5 je funkce rostoucí (její první derivace je v tomto intervalu

NMAF 051, ZS Zkoušková písemná práce 16. ledna 2009

Union-Find problém. Kapitola 1

NP-úplnost problému SAT

Intervalové stromy. Představme si, že máme posloupnost celých čísel p 0, p 1,... p N 1, se kterou budeme. 1. Změna jednoho čísla v posloupnosti.

5 Rekurze a zásobník. Rekurzivní volání metody

V předchozí kapitole jsme podstatným způsobem rozšířili naši představu o tom, co je to číslo. Nadále jsou pro nás důležité především vlastnosti

7. Geometrické algoritmy (sepsal Pavel Klavík)

Základy algoritmizace c2007 Michal Krátký, Jiří Dvorský 1/57

PŘEDNÁŠKA 2 POSLOUPNOSTI

Maturitní téma: Programovací jazyk JAVA

Reprezentace aritmetického výrazu - binární strom reprezentující aritmetický výraz

fakulty MENDELU v Brně (LDF) s ohledem na disciplíny společného základu (reg. č. CZ.1.07/2.2.00/28.

které je z různých pohledů charakterizují. Několik z nich dokážeme v této kapitole.

p 2 q , tj. 2q 2 = p 2. Tedy p 2 je sudé číslo, což ale znamená, že

Výhody a nevýhody jednotlivých reprezentací jsou shrnuty na konci kapitoly.

5. Lokální, vázané a globální extrémy

Radek Mařík

Unární je také spojka negace. pro je operace binární - příkladem může být funkce se signaturou. Binární je velká většina logických spojek

Základní datové struktury III: Stromy, haldy

Obsah prezentace. Základní pojmy v teorii o grafech Úlohy a prohledávání grafů Hledání nejkratších cest

Algebraické rovnice. Obsah. Aplikovaná matematika I. Ohraničenost kořenů a jejich. Aproximace kořenů metodou půlení intervalu.

Báze a dimenze vektorových prostorů

5. Náhodná veličina. 2. Házíme hrací kostkou dokud nepadne šestka. Náhodná veličina nabývá hodnot z posloupnosti {1, 2, 3,...}.

LDF MENDELU. Simona Fišnarová (MENDELU) Základy lineárního programování VMAT, IMT 1 / 25

f(c) = 0. cn pro f(c n ) > 0 b n pro f(c n ) < 0

Limita a spojitost funkce

0. Lineární rekurence Martin Mareš,

PŘEDNÁŠKA 7 Kongruence svazů

Modely Herbrandovské interpretace

13. Třídící algoritmy a násobení matic

Zpracoval: 7. Matematická indukce a rekurse. Řešení rekurentních (diferenčních) rovnic s konstantními koeficienty.

FIT ČVUT MI-LOM Lineární optimalizace a metody. Dualita. Evropský sociální fond Praha & EU: Investujeme do vaší budoucnosti

1 Lineární prostory a podprostory

O dělitelnosti čísel celých

Stromové struktury v relační databázi

19. Druhý rozklad lineární transformace

Generování pseudonáhodných. Ing. Michal Dorda, Ph.D.

1. DIFERENCIÁLNÍ POČET FUNKCE DVOU PROMĚNNÝCH

Často potřebujeme hledat mezi dvěma vrcholy grafu cestu, která je v nějakém

opakování reprezentace grafů, dijkstra, bellman-ford, johnson

Výroková a predikátová logika - IV

Kapitola 1. Úvod. 1.1 Značení. 1.2 Výroky - opakování. N... přirozená čísla (1, 2, 3,...). Q... racionální čísla ( p, kde p Z a q N) R...

Kongruence na množině celých čísel

3. Prohledávání grafů

Monotonie a lokální extrémy. Konvexnost, konkávnost a inflexní body. 266 I. Diferenciální počet funkcí jedné proměnné

Vyhledávání. doc. Mgr. Jiří Dvorský, Ph.D. Katedra informatiky Fakulta elektrotechniky a informatiky VŠB TU Ostrava. Prezentace ke dni 21.

IB108 Sada 1, Příklad 1 Vypracovali: Tomáš Krajča (255676), Martin Milata (256615)

Prioritní fronta, halda

1. Několik základních pojmů ze středoškolské matematiky. Na začátku si připomeneme následující pojmy:

M - Příprava na 1. zápočtový test - třída 3SA

Vrcholová barevnost grafu

α β ) právě tehdy, když pro jednotlivé hodnoty platí β1 αn βn. Danou relaci nazýváme relace

Definice. B-stromu. B-strom řádu m je strom, kde každý uzel má maximálně m následníků a ve kterém platí:

STROMOVE ALGORITMY Prohledavani do sirky (level-order) Po vodorovnejch carach fronta

Datové struktury Úvod

Dynamické datové struktury III.

Další NP-úplné problémy

Výroková a predikátová logika - V

Algoritmy na ohodnoceném grafu

Složitosti základních operací B + stromu

1. Základní pojmy, používané v tomto manuálu. 2. Stránky

Algoritmizace složitost rekurzivních algoritmů. Jiří Vyskočil, Marko Genyg-Berezovskyj 2010

Transkript:

1. Vledávací strom V minulé kapitole jsme se vdali po stopě datovýc struktur pro efektivní reprezentaci množin a slovníků. To nás nní dovede k různým variantám vledávacíc stromů. Začneme těmi binárními, ale později zjistíme, že se může odit uvažovat o stromec obecněji. 1.1. Binární vledávací strom Jak jsme viděli, uspořádané pole umí rcle vledávat, ale veškeré změn trvají dlouo. Pokusíme se proto od pole přejít k obecnější struktuře, která bude pružnější. Zavzpomínejme, jak se ledá v uspořádaném poli. Zvolíme prvek uprostřed pole, porovnáme o s ledaným a podle výsledku porovnání se zaměříme buďto na levý nebo na pravý interval. Tam opakujeme stejný algoritmus. Jelikož velikosti intervalů klesají eponenciálně, zastavíme se po O(log n) krocíc. Možné průbě vledávání můžeme popsat stromem. Kořen stromu odpovídá prvnímu porovnání: obsauje prostřední prvek pole a má dva sn levéo a pravéo. Ti odpovídají dvěma možným výsledkům porovnání: pokud je ledaná odnota menší, jdeme doleva; pokud větší, tak doprava. Následující vrcol nám řekne, jaké další porovnání máme provést, a tak dále až do dob, kd buďto nastane rovnost (takže jsme našli), nebo se pokusíme přejít do neeistujícío vrcolu (takže ledaná odnota v poli není). Pro úspěšné vledávání přitom nepotřebujeme, abcom z každéo intervalu vbrali právě ten prostřední prvek. Pokud bcom volili jinak, dostaneme odlišný strom. Pomocí něj také půjde ledat, jen možná pomaleji to je vidět na následujícím obrázku. Fi! 7 4 v 4 9 2 5 l(v) r(v) (v) 2 5 8 7 8 L(v) R(v) 9 T (v) Obr. 1.1: Dva binární vledávací strom a jejic značení Co všecno musí strom splňovat, ab se podle něj dalo ledat, přetavíme do nasledujícíc definic. Fi: Zmínit rozodovací strom z kapitol o třídění. 1 2016-01-25

Definice: Strom T nazveme binární, pokud je zakořeněný a každý vrcol v V (T ) má nejvýše dva sn, u nicž rozlišujeme, který je levý a který pravý. Definice: Pro vrcol v binárnío stromu T značíme: l(v) a r(v) levý a pravý sn vrcolu v L(v) a R(v) levý a pravý podstrom vrcolu v T (v) podstrom obsaující vrcol v a všecn jeo potomk (v) loubka stromu T (v), čili maimum z délek cest z v do listů Pokud vrcol nemá levéo sna, položíme l(v) = a podobně pro r(v) a p(v). Pak se odí dodefinovat, že T ( ) je prázdný strom a ( ) = 1. Definice: Binární vledávací strom (BVS) je binární strom, jeož každému vrcolu v přiřadíme unikátní klíč k(v) z universa. Přitom musí pro každý vrcol v platit: Kdkoliv u L(v), pak k(u) < k(v). Kdkoliv u R(v), pak k(u) > k(v). Operace s BVS Pomocí vledavacíc stromů můžeme přirozeně reprezentovat množin: klíče uložené ve vrcolec budou odpovídat prvkům množin. kdbcom místo množin ctěli slovník, přidáme do vrcolu odnotu přiřazenou danému klíči. Nní ukážeme, jak provádět jednotlivé množinové operace. Jelikož strom jsou definované rekurzivně, je přirozené zacázet s nimi rekurzivními funkcemi. Dobře je to vidět na následující funkci, která vpíše všecn prvk množin. Definice BVS nám dokonce zaručuje, že budou vpsán v pořadí od nejmenšío k největšímu. Procedura BvsSow Vstup: Kořen BVS v 1. Pokud v =, jedná se o prázdný strom a ned skončíme. 2. Zavoláme BvsSow(l(v)). 3. Vpíšeme klíč uložený ve vrcolu v. 4. Zavoláme BvsSow(r(v)). Funkce BvsFind slouží k nalezení vrcolu s daným klíčem. Procází stromem od kořene a každý vrcol v porovná s. Pokud je < k(v), pak se podle definice nemůže nacázet v pravém podstromu, takže pokračujeme doleva. Je-li naopak > k(v), nic nepokazíme krokem doprava. V konečném čase proto buďto najdeme, nebo vloučíme všecn možnosti, kde b se molo nacázet. BvsFind formulujeme jako rekurzivní funkci, kterou vžd voláme na kořen nějakéo podstromu a vrátí nám nový kořen. Procedura BvsFind Vstup: Kořen BVS v, ledaný klíč 1. Pokud v =, vrátíme. 2. Pokud = k(v), vrátíme v. 2 2016-01-25

3. Pokud < k(v), vrátíme BvsFind(l(v), ). 4. Pokud > k(v), vrátíme BvsFind(r(v), ). Výstup: Vrcol s klíčem, anebo. Minimum z prvků množin spočteme snadno: půjdeme stále doleva, dokud to jde. Klíče menší než ten aktuální se totiž moou nacázet pouze v levém podstromu. Procedura BvsMin Vstup: Kořen BVS v 1. Pokud l(v) =, vrátíme vrcol v. 2. Jinak vrátíme BvsMin(l(v)). Výstup: Vrcol obsaující nejmenší klíč Vkládání novéo prvku funguje velmi podobně jako vledávání s tím rozdílem, že v okamžiku, kd b vledávací algoritmus měl přejít do neeistujícío vrcolu, tento nový vrcol vtvoříme a vložíme do něj vkládaný prvek. Rozmslíme si, že toto je jediné místo, kde podle definice nový prvek smí ležet. Procedura BvsInsert Vstup: Kořen BVS v, vkládaný klíč 1. Pokud v =, vtvoříme nový vrcol v s klíčem. 2. Pokud < k(v), položíme l(v) BvsInsert(l(v), ). 3. Pokud > k(v), položíme r(v) BvsInsert(r(v), ). 4. Pokud = k(v), klíč se ve stromu již nacází, není třeba nic měnit. Výstup: Nový kořen v Při mazání může nastat několik různýc případů. Necť v je vrcol, který cceme smazat. Je-li v list, můžeme tento list prostě odstranit, čímž vlastně provedeme operaci opačnou k BvsInsertu. Má-li v právě jednoo sna, postačí v naradit tímto snem. Ošemetný je případ se dvěma sn. Ted totiž nemůžeme v jen tak smazat, jelikož b tto sn neblo kam připojit. Proto nalezneme následníka vrcolu v, což je nejlevější vrcol v pravém podstromu. Ten má nejvýše jednoo sna, takže o smažeme místo v a jeo odnotu přesuneme do v. Procedura BvsDelete Vstup: Kořen BVS v, mazaný klíč 1. Pokud v =, vrátíme. (Klíč ve stromu nebl.) 2. Pokud < k(v), položíme l(v) BvsDelete(l(v), ). 3. Pokud > k(v), položíme r(v) BvsDelete(r(v), ). 4. Pokud = k(v): (Cstáme se smazat vrcol v.) 5. Pokud l(v) = r(v) =, vrátíme. (Bl to list.) 6. Pokud l(v) =, vrátíme r(v). (Eistoval jen pravý sn.) 7. Pokud r(v) =, vrátíme l(v). (Eistoval jen levý sn.) 8. s BvsMin(r(v)) (Máme oba sn: nalezneme následníka s.) 3 2016-01-25

9. k(v) k(s). 10. r(v) BvsDelete(r(v), s) 11. Vrátíme v. Výstup: Nový kořen v Vváženost stromů Zamsleme se nad složitostí stromovýc operací pro strom na n vrcolec. BvsSow projde všecn vrcol a v každém stráví konstantní čas, takže běží v čase Θ(n). Ostatní operace projdou po nějaké cestě od kořene směrem k listům, a to buďto jednou, nebo (v nejsložitějším případě BvsDelete) dvakrát. Jejic časová složitost proto bude Θ(loubka stromu). Hloubka přitom závisí na tom, jak moc je strom košatý. V příznivém případě vjde smpatickýc O(log n), ovšem dalšími operacemi může může strom degenerovat. Například začneme-li s prázdným stromem a postupně vložíme klíče 1,..., n v tomto pořadí, vznikne liána loubk Θ(n). Budeme se proto snažit strom vvažovat, ab jejic loubka příliš nerostla. Zkusme se opět držet paralel s binárním vledáváním. Definice: Binární vledávací strom nazveme dokonale vvážený, pokud pro každý jeo vrcol v platí L(v) P (v) 1. Jinými slov velikost levéo a pravéo podstromu se smí lišit nejvýše o 1 vrcol. Pozorování: Dokonale vvážený strom má loubku log 2 n, jelikož na kterékoliv cestě z kořene do listu velikost podstromů s každým krokem klesá alespoň dvakrát. Dokonale vvážený strom ted zaručuje rclé vledávání. Navíc pokud všecn prvk množin známe předem, můžeme si takový strom snadno pořídit: z uspořádané posloupnosti o vtvoříme v lineárním čase (viz cvičení 3). Tím boužel dobré zpráv končí: ukážeme, že po vložení nebo smazání vrcolu nelze dokonalou vváženost obnovit rcle. Věta: Pro každou implementaci operací Insert a Delete v dokonale vváženém stromu platí, že buď Insert nebo Delete trvá Ω(n). Důkaz: Nejprve si představíme, jak bude vpadat dokonale vvážený BVS s klíči 1,..., n, kde n = 2 k 1. Sledujme obrázek 1.2. Tvar stromu je určen jednoznačně: Kořenem musí být prostřední z klíčů (jinak b se levý a pravý podstrom kořene lišil o více než 1 vrcol). Levý a pravý podstrom proto mají právě (n 1)/2 = 2 k 1 1 vrcolů, takže jejic kořen jsou opět určen jednoznačně a tak dále. Navíc si všimneme, že všecna licá čísla jsou umístěna v listec stromu. Nní na tomto stromu provedeme následující posloupnost operací: Insert(n + 1), Delete(1), Insert(n + 2), Delete(2),... 4 2016-01-25

8 4 12 2 6 10 14 1 3 5 7 9 11 13 15 Obr. 1.2: Dokonale vvážený BVS Po provedení i-té dvojice operací bude strom obsaovat odnot i + 1,..., i + n. Podle too, zda je i sudé nebo licé, se budou v listec nacázet buď všecna sudá, nebo všecna licá čísla. Pokaždé se proto všem vrcolům změní, zda jsou list, na což je potřeba upravit Ω(n) ukazatelů. Ted aspoň jedna z operací Insert a Delete trvá Ω(n). Cvičení 1. Rekurze je pro operace s BVS přirozená, ale v některýc programovacíc jazcíc je pomalejší než občejný cklus. Navrněte, jak operace s BVS naprogramovat nerekurzivně. 2. Místo vrcolu se dvěma sn jsme mazali jeo následníka. Samozřejmě bcom si místo too moli vbrat předcůdce. Jak b se algoritmus změnil? 3. Navrněte algoritmus, který ze setříděnéo pole vrobí v lineárním čase dokonale vvážený BVS. 4. Navrněte algoritmus, který v lineárním čase zadaný BVS dokonale vváží. 5**. Vřešte předcozí cvičení tak, ab vám kromě zadanéo stromu stačilo konstantní množství paměti. Pokud nevíte, jak na to, zkuste to nejprve s logaritmickou pamětí. 6. Navrněte algoritmus, který dostane dva BVS T 1 a T 2 sloučí jejic obsa do jedinéo BVS. lgoritmus b měl pracovat v čase O( T 1 + T 2 ). 7. Navrněte operaci BvsSplit, která dostane BVS T a odnotu s, a rozdělí strom na dva BVS T 1 a T 2 takové, že odnot v T 1 jsou menší než s a odnot v T 2 jsou větší než s. 8. Naše tvrzení o náročnosti operací Insert a Delete v dokonale vváženém stromu lze ještě zesílit. Dokažte, že lineární musí být složitost obou operací. 1.2. Hloubkové vvá¾ení: VL strom Zjistili jsme, že dokonale vvážené strom nelze efektivně udržovat. Důvodem je, že jejic definice velmi striktně omezuje tvar stromu, takže i vložení jedinéo klíče může vnutit přebudování celéo stromu. Zavedeme proto o trocu slabší podmínku. 5 2016-01-25

Definice: Binární vledávací strom nazveme loubkově vvážený, pokud pro každý jeo vrcol v platí (l(v)) (r(v)) 1. Jinými slov loubka levéo a pravéo podstromu se vžd musí lišit nejvýše o jedna. Stromům s loubkovým vvážením se říká VL strom, neboť je vmsleli v roce 1962 ruští matematikové G. M. děľson-veľskij a E. M. Landis. Nní dokážeme, že VL strom mají logaritmickou loubku. Tvrzení: VL strom na n vrcolec má loubku Θ(log n). Důkaz: Nejprve pro každé 0 stanovíme, což bude minimální možný počet vrcolů v VL stromu loubk, a dokážeme, že tento počet roste s loubkou eponenciálně. Pro malá stačí rozebrat možné případ podle obrázku 1.3. 0 = 1 1 = 2 2 = 4 3 = 7 = 1 + 2 + 1 1 2 Obr. 1.3: Minimální VL strom pro loubk 0 až 3 a obecný případ Pro větší uvažujme, jak může minimální VL strom o ladinác vpadat. Jeo kořen musí mít dva podstrom, jeden z nic loubk 1 a druý loubk 2 (kdb měl také 1, měl b zbtečně mnoo vrcolů). Oba tto podstrom musí být minimální VL strom dané loubk. Musí ted platit = 1 + 2 + 1. To je rekurence podobná té z Fibonaccio posloupnosti. Vskutku: platí = F +3 1, kde F k je k-té Fibonaccio číslo. Z too bcom moli získat eplicitní vzorec pro, ale pro dukaz našeo tvrzení postačí jednodušší asmptotický odad. Dokážeme indukcí, že 2 /2. Jistě je 0 = 4 2 0/2 = 1 a 1 = 2 2 1/2. = 1.414. Indukční krok pak vpadá následovně: = 1 + 1 + 2 > 2 1 2 + 2 2 2 = 2 2 (2 1 2 + 2 1 ) 2 2 1.2 > 2 2. Tím jsme dokázali, že c pro c = 2. Proto VL strom o n vrcolec může mít nejvýše log c n ladin kdb jic měl více, obsaoval b více než c log c n = n vrcolů. Zbývá dokázat, že logaritmická loubka je také nutná. K tomu dojdeme podobně: nalédneme, že největší možný VL strom loubk je úplný binární strom s 2 +1 1 vrcol. Tudíž minimální možná loubka VL stromu je Ω(log n). 6 2016-01-25

Vvažování rotacemi Jak budou vpadat operace na VL stromec? Find bude totožný. Operace Insert a Delete začnou stejně jako u obecnéo BVS, ale poté ještě ověří, zda strom zůstal loubkově vvažený, a případně zasánou, ab se vváženost obnovila. bcom poznali, kd je zása potřeba, budeme v každém vrcolu v udržovat číslo δ(v) = (r(v)) (l(v)). To je takzvané znaménko vrcolu, které v korektním VL stromu může nabývat jen těcto odnot: δ(v) = 1 (pravý podstrom je lubší) takový vrcol značíme, δ(v) = 1 (levý podstrom lubší) značíme, δ(v) = 0 (oba podstrom stejně luboké) značíme. Jakmile narazíme na jiné δ(v), strom opravíme provedením jedné nebo více rotací. Rotace je operace, která otočí ranu mezi dvěma vrcol a přepojí jejic podstrom tak, ab bli i nadále snové vzledem k otcům správně uspořádáni. To lze provést jediným způsobem, který najdete na obrázku 1.4. Často také potkáme dvojitou rotaci z obrázku 1.5. Tu lze složit ze dvou jednoducýc rotací, ale bývá přelednější uvažovat o ní vcelku jako o překořenění celé konfigurace za vrcol. C B B C Obr. 1.4: Jednoducá rotace z z D B C D B C Obr. 1.5: Dvojitá rotace Vkládání do stromu Nový prvek vložíme jako list se znaménkem. Tím se z prázdnéo podstromu loubk 1 stal jednovrcolový podstrom loubk 0, takže může být potřeba přepočítat znaménka na cestě ke kořeni. 7 2016-01-25

Proto se budeme vracet do kořene a propagovat do vššíc pater informaci o tom, že se podstrom proloubil. (To můžeme elegantně provést běem návratu z rekurze v proceduře BvsInsert.) Ukážeme, jak bude vpadat jeden krok. Necť do nějakéo vrcolu přišla z jeo sna informace o proloubení podstromu. Bez újm na obecnosti se jednalo o levéo sna v opačném případě provedeme vše zrcadlově a proodíme roli znamének a. Rozlišíme několik případů. Případ 1: Vrcol měl znaménko. Hloubka levéo podstromu se právě vrovnala s loubkou pravéo, čili znaménko se změní na. Hloubka podstromu T () se nezměnila, takže propagování informace ukončíme. Případ 2: Vrcol měl znaménko. Znaménko se změní na. Hloubka podstromu T () vzrostla, takže v propagování musíme pokračovat. Případ 3: Vrcol měl znaménko, ted teď získá δ(v) = 2. To definice VL stromu nedovoluje, takže musíme strom vvážit. Označme vrcol, z nějž přišla informace o proloubení, čili levéo sna vrcolu. Rozebereme případ podle jeo znaménka. Případ 3a: Vrcol má znaménko. Situaci sledujme na obrázku. Označíme-li loubku podstromu C, podstrom T () má loubku +2, takže podstrom má loubku +1 a podstrom B loubku. Provedeme rotaci ran. Tím získá vrcol znaménko, podstrom T () loubku + 1, vrcol znaménko a podstrom T () loubku + 2. Jelikož před započetím operace Insert měl podstrom T () loubku + 2, z poledu vššíc pater se nic nezměnilo. Propagování ted opět zastavíme. 2 0 + 2 + 1 B C + 1 0 B C + 1 Případ 3b: Vrcol má znaménko. Sledujme opět obrázek. Označíme z pravéo sna vrcolu (uvědomte si, že musí eistovat). 8 2016-01-25

Označíme jednotlivé podstrom tak jako na obrázku a spočítáme jejic loubk. Referenční loubku zvolíme podle podstromu D. Hloubk znamenají buď nebo 1. Provedeme dvojitou rotaci, která celou konfiguraci překoření za vrcol z. Přepočítáme loubk a znaménka. Vrcol bude mít znaménko buď nebo, vrcol buď nebo, každopádně oba podstrom T () a T () získají loubku +1. Proto vrcol z získá znaménko. Před započetním Insertu činila loubka celé konfigurace +2, nní je také + 2, takže propagování zastavíme. + 2 + B z 2 C D + 1 z 0 + 1 + 1 B C D Případ 3c: Vrcol má znaménko. Tento případ je ze všec nejjednodušší nemůže totiž nikd nastat. Z vrcolu se znaménkem se informace o proloubení v žádném z předcozíc případů nešíří. Mazání ze stromu Budeme postupovat obdobně jako u Insertu: vrcol smažeme podle původnío algoritmu BvsDelete a po cestě zpět do kořene propagujeme informaci o snížení loubk podstromu. Připomeňme, že pokaždé mažeme list nebo vrcol s jediným snem, takže stačí propagovat od místa smazanéo vrcolu naoru. Opět popíšeme jeden krok propagování. Necť do vrcolu přišla informace o snížení loubk podstromu, bez újm na obecnosti z levéo sna. Rozlišíme následující případ. Případ 1: Vrcol má znaménko. Hloubka levéo podstromu se právě vrovnala s loubkou pravéo, znaménko se mění na. Hloubka podstromu T () se snížila, takže pokračujeme v propagování. Případ 2: Vrcol má znaménko. Znaménko se změní na. Hloubka podstromu T () se nezměnila, takže propagování ukončíme. 9 2016-01-25

Případ 3: Vrcol má znaménko. Ted se jeo znaménko změní na +2 a musíme vvažovat. Rozebereme tři případ podle znaménka pravéo sna vrcolu. (Všimněte si, že na rozdíl od vvažování po Insertu to musí být opačný sn než ten, ze kteréo přišla informace o změně loubk.) Případ 3a: Vrcol má také známénko. Označíme-li loubku podstromu, bude mít T () loubku + 2, takže C loubku + 1 a B loubku. Provedeme rotaci ran. Tím vrcol získá znaménko, podstrom T () loubku + 1, takže vrcol dostane také znaménko. Před započetím Delete měl podstrom T () loubku + 3, nní má T () loubku + 2, takže z poledu vššíc ladin došlo ke snížení loubk. Proto změnu propagujeme dál. +2 0 B + C + 1 + 2 + 1 0 B C + 1 Případ 3b: Vrcol má znaménko. Necť je loubka podstromu. Pak T () má loubku + 2 a B i C loubku + 1. Provedeme rotaci ran. Vrcol získává znaménko, podstrom T () loubku + 2, takže vrcol obdrží znaménko. Hloubka podstromu T () před začátkem Delete činila + 3, nní má podstrom T () loubku také + 3, pročež propagování ukončíme. +2 0 B C + 1 + 1 + 2 + 2 + B + 1 C + 1 Případ 3c: Vrcol má znaménko. Označíme z levéo sna vrcolu. 10 2016-01-25

Označíme podstrom podle obrázku a spočítáme jejic loubk. Referenční loubku zvolíme opět podle. Hloubk znamenají buď nebo 1. Provedeme dvojitou rotaci, která celou konfiguraci překoření za vrcol z. Přepočítáme loubk a znaménka. Vrcol bude mít znaménko buď nebo, buď nebo. Podstrom T () a T () budou každopádně luboké + 1. Proto vrcol z obdrží znaménko. Původní loubka podstromu T () před začatkem Delete činila + 3, nní loubka T (z) činí + 2, takže propagujeme dál. + 1 +2 z D B C + 2 z 0 + 1 + 1 B C D Složitost operací Dokázali jsme, že loubka VL stromu je vžd O(log n). Původní implementace operací BvsFind, BvsInsert a BvsDelete ted pracují v logaritmickém čase. Po BvsInsert a BvsDelete ještě musí následovat vvážení, které se ovšem vžd vrací po cestě do kořene a v každém vrcolu provede O(1) operací, takže celkově také trvá O(log n). Cvičení 1. Dokažte, že pro minimální velikost k VL stromu loubk k platí vzta k = F k+3 1 (kde F n je n-té Fibonaccio číslo). Z too odvoďte přesný vzorec pro minimální a maimální možnou loubku VL stromu na n vrcolec. 2. Při vvažování po Insertu jsme se nemuseli zabývat případem 3c proto, že z se informace o proloubení nikd nešíří. Nemůžeme stejným způsobem dokázat, že případ 3b také nikd nenastane? (Pozor, cták!) 3. Upravte VL strom tak, ab dokázal pro libovolné k najít k-tý nejmenší prvek. Pokud doplníte nějaké další informace do vrcolů stromu, nezapomeňte, že je musíte udržovat i při vvažování. 1.3. Více klíèù ve vrcolec: (a,b)-strom Nní prozkoumáme obecnější variantu vledávacíc stromů, která připouští proměnlivý počet klíčů ve vrcolec. Tím si sice trocu zkomplikujeme úva 11 2016-01-25

o struktuře stromů, ale za odměnu získáme přímočařejší vvažovací algoritm bez složitéo rozboru případů. Definice: Obecný vledávací strom je zakořeněný strom s určeným pořadím snů každéo vrcolu. Vrcol dělíme na vnitřní a vnější, přičemž platí: Vnitřní (interní) vrcol obsaují klíče, v každém obecně jiný počet. Pokud vrcol obsauje klíče 1 <... < k, pak má k + 1 snů, které označíme s 0,..., s k. Klíče slouží jako oddělovače odnot v podstromec, čili platí: T (s 0 ) < 1 < T (s 1 ) < 2 <... < k 1 < T (s k 1 ) < k < T (s k ), kde T (s i ) značí množinu všec klíčů z danéo podstromu. Často se odí dodefinovat 0 = a k+1 = +, ab nerovnost i < T (s i ) < i+1 platila i pro krajní sn. Vnější (eterní) vrcol neobsaují žádná data a nemají žádné potomk. Jsou to ted list stromu. Na obrázku je značíme jako malé čtverečk, v programu je můžeme reprezentovat nulovými ukazateli (NULL v jazku C, nil v Pascalu). Podobně jako BVS, i obecné vledávací strom moou degenerovat. Přidáme proto další podmínk pro zajištění vváženosti. Definice: (a,b)-strom pro parametr a 2, b 2a 1 je obecný vledávací strom, pro který navíc platí: 1. Kořen má 2 až b snů, ostatní vnitřní vrcol a až b snů. 2. Všecn vnější vrcol jsou ve stejné loubce. Požadavk na a a b moou vpadat tajemně, ale jsou snadno splnitelné a později vplne, proč jsme je potřebovali. Ccete-li konkrétní příklad, představujte si ten nejmenší možný: (2, 3)-strom. Vše ovšem budeme odvozovat obecně. Přitom budeme předpokládat, že a a b jsou konstant, které se moou scovat do O. Později prozkoumáme, jaký vliv má volba těcto parametrů na vlastnosti struktur. Nní začneme odadem loubk. Lemma: (a, b)-strom s n klíči má loubku Θ(log n). Důkaz: Počítejme minimální počet klíčů m ve stromu loubk 1. Vrcol budou obsaovat minimální povolené počt klíčů a rozdělíme je podle loubk do ladin: na 0-té ladině je kořen se dvěma klíči, na -té leží list bez klíčů, na mezilelýc ladinác ostatní vnitřní vrcol s a 1 klíči. Na i-té ladině bude ted ležet 2 a i 1 vrcolů. Sečtením přes ladin získáme: 1 2 m = 1 + (a 1) 2 a i 1 = 1 + 2 (a 1) a j. i=1 Sečteme-li geometrickou řadu v poslední sumě, dostaneme: m = 1 + 2 (a 1) a 1 1 a 1 j=0 = 1 + 2 (a 1 1) = 2a 1 1. 12 2016-01-25

Víme ted, že minimální počet klíčů roste s loubkou eponenciálně. Proto maimální loubka musí s počtem klíčů růst nejvýše logaritmick. (Srovnejte s výpočtem maimální loubk VL stromů.) Podobně spočítáme, že maimální počet klíčů M roste také eponenciálně, takže minimální možná loubka je také logaritmická. Tentokrát uvážíme strom, jeož všecn vnitřní vrcol včetně kořene obsaují nejvšší povolený počet b 1 klíčů: Hledání klíče 1 M = (b 1) b i = (b 1) b 1 b 1 = b 1. i=0 Hledání klíče v (a, b)-stromu probíá podobně jako v BVS: začneme v kořeni a v každém vnitřním vrcolu se porovnáváním s jeo klíči rozodneme, do kteréo podstromu se vdat. Přitom buď narazíme na ledaný klíč, nebo dojdeme až do listu a tam skončíme s nepořízenou. Vkládání do stromu Při vkládání nejprve zkusíme nový klíč vledat. Pokud ve stromu ještě není přítomen, skončíme v nějakém listu. Nabízí se změnit list na vnitřní vrcol přidáním jednoo klíče a dvou listů jako snů. Tím bcom ovšem porušili aiom o stejné loubce listů. Raději se proto zaměříme na otce nalezenéo listu a vložíme klíč do něj. To nás donutí přidat jednoo sna, ale jelikož ostatní snové jsou list, i tento může být list. Pokud jsme přidáním klíče vrcol nepřeplnili (má nadále nejvýš b 1 klíčů), jsme otovi. Pakliže jsme vrcol přeplnili, rozdělíme jeo klíče mezi dva nové vrcol, přibližně napůl. K nadřazenému vrcolu ovšem musíme místo jednoo sna připojit dva nové, takže v nadřazeném vrcolu musí přibýt klíč. Proto přeplněný vrcol raději rozdělíme na tři části: prostřední klíč, který budeme vkládat o patro výš, a levou a pravou část, z nicž se stanou nové vrcol. Tím jsme vložení klíče do aktuálnío vrcolu převedli na tutéž operaci o patro výš. Tam může opět dojít k přeplnění a následnému štěpení vrcolu a tak dále, možná až do kořene. Pokud rozštěpíme kořen, vtvoříme nový kořen s jediným klíčem a dvěma sn (zde se odí, že jsme kořeni dovolili mít méně než a snů) a celý strom se o ladinu proloubí. Naše ukázková implementace má podobu rekurzivní funkce BInsert2(v, ), která dostane za úkol vložit do podstromu s kořenem v klíč. Jako výsledek vrátí trojici (p,, q), pokud došlo k štěpení vrcolu v na vrcol p a q oddělené klíčem, anebo, pokud v zůstalo kořenem podstromu. Hlavní procedura BInsert navíc ošetřuje případ štěpení kořene. Obr 13 2016-01-25

Procedura BInsert Vstup: Kořen stromu r, vkládaný klíč 1. t BInsert2(r, ) 2. Pokud t má tvar trojice (p,, q): 3. r nový kořen s klíčem a sn p a q Výstup: Nový kořen r Procedura BInsert2(v, ) Vstup: Kořen podstromu v, vkládaný klíč 1. Pokud v je list, skončíme a vrátíme trojici (l 1,, l 2 ), kde l 1 a l 2 jsou nově vtvořené list. 2. Označíme 1,..., k klíče ve vrcolu v a s 0,..., s k jeo sn. 3. Pokud = i pro nějaké i, skončíme a vrátíme. 4. Najdeme i tak, ab platilo i < < i+1 ( 0 =, k+1 = + ). 5. t BInsert2(s i, ) 6. Pokud t =, skončíme a také vrátíme. 7. Označíme (p,, q) složk trojice t. 8. Mezi klíče i a i+1 vložíme klíč. 9. Sna s i naradíme dvojicí snů p a q. 10. Pokud počet snů nepřekročil b, skončíme a vrátíme. 11. m (b 1)/2 (Došlo k štěpení, volíme prostřední klíč.) 12. Vtvoříme nový vrcol v 1 s klíči 1,..., m 1 a sn s 0,..., s m 1. 13. Vtvoříme nový vrcol v 2 s klíči m+1,..., b a sn s m,..., s b+1. 14. Vrátíme trojici (v 1, m, v 2 ). Zbývá dokázat, že vrcol vznikné štěpením mají dostatečný počet snů. Vrcol v jsme rozštěpili v okamžiku, kd dosál právě b + 1 snů, a ted obsaoval b klíčů. Jeden klíč posíláme o patro výš, takže novým vrcolům v 1 a v 2 přidělíme po řadě (b 1)/2 a (b 1)/2 klíčů. Kdb některý z nic bl podměrečný, muselo b platit (b 1)/2 < a 1, a ted b 1 < 2a 2, čili b < 2a 1. Ejle, podmínka na b v definici (a, b)-stromu bla zvolena přesně tak, ab této situaci zabránila. Mazání ze stromu Cceme-li ze stromu smazat nějaký klíč, nejprve o vledáme. Pokud se nacází na předposlední ladině (té, pod níž jsou už pouze list), můžeme o smazat přímo, jen musíme ošetřit případné podtečení vrcolu. Klíče ležící na vššíc ladinác nemůžeme mazat jen tak, neboť smazáním klíče přicázíme i o místo pro připojení podstromu. To je situace podobná mazání vrcolu se dvěma sn v binárním stromu a vřešíme ji také podobně. Mazaný klíč naradíme jeo následníkem. To je nejlevější vrcol v pravém podstromu, který tudíž leží na předposlední ladině a může být smazán přímo. 14 2016-01-25

Zbývá ted vřešit, co se má stát v případě, že vrcol v s a sn přijde o klíč, takže už je pod míru. Ted budeme postupovat opačně než při vkládání pokusíme se vrcol sloučit s některým z jeo bratrů. To je ovšem možné provést pouze ted, kdž bratr také obsauje málo klíčů; pokud jic naopak obsauje odně, nějaký klíč si od něj můžeme půjčit. Nní popíšeme, jak to přesně provést. Bez újm na obecnosti předpokládejme, že vrcol v má pravéo bratra b oddělenéo nějakým klíčem o v otci. Pokud b eistoval pouze levý bratr, vbereme too a následující postup provedeme zrcadlově převrácený. Pokud má bratr pouze a snů, sloučíme vrcol v a b do jedinéo vrcolu a přidáme do něj ještě klíč o z otce. Tím vznikne vrcol s (a 2) + (a 1) + 1 = 2a 2 klíči, což není větší než b 1. Problém jsme ted převedli na mazání klíče z otce, což je tentýž problém o ladinu výš. Má-li naopak bratr více jak a snů, odpojíme od něj jeo nejlevějšío sna l a nejmenší klíč m. Poté klíč m přesuneme do otce a klíč o odtamtud přesuneme do v, kde se stane nejpravějším klíčem, za který přepojíme sna l. Poté mají v i b povolené počt snů a můžeme skončit. (Všimněte si, že tato operace je podobná rotaci ran v binárním stromu.) Nní tento postup zapíšeme jako rekurzivní proceduru BDelete2. Ta dostane kořen podstromu a klíč, který má smazat. Jako výsledek vrátí vrátí podstrom s tímtéž kořenem, ovšem možná podměrečným. Hlavní procedura BDelete navíc ošetřuje případ, kd z kořene zmizí všecn klíče, takže je potřeba kořen smazat a tím snížit celý strom o ladinu. Procedura BDelete Vstup: Kořen stromu r a mazaný klíč 1. Zavoláme BDelete2(r, ). 2. Pokud r má jedinéo sna s: 3. Zrušíme vrcol r. 4. r s Výstup: Nový kořen r Obr Procedura BDelete2 Vstup: Kořen podstromu v a mazaný klíč 1. Označíme 1,..., k klíče ve vrcolu v a s 0,..., s k jeo sn. 2. Pokud = i pro nějaké i: (Našli jsme) 3. Pokud s i je list: (Jsme na předposlední ladině.) 4. Odstraníme z v klíč i a list s i. 5. Skončíme. 6. Jinak: (Jsme výš, musíme narazovat.) 7. m minimum podstromu s kořenem s i 8. i m 9. Zavoláme BDelete2(s i, m). 15 2016-01-25

10. Jinak: (Mažeme z podstromu.) 11. Najdeme i takové, ab i < < i+1 ( 0 =, k+1 = + ). 12. Pokud s i je list, skončíme. (Klíč ve stromu není.) 13. Zavoláme BDelete2(s i, ). 14. (Vrátili jsme se z s i a kontrolujeme, zda tento sn není pod míru.) 15. Pokud s i má alespoň a snů, skončíme. 16. Je-li i < k: (Eistuje pravý bratr s i+1.) 17. Pokud má s i+1 alespoň a + 1 snů: (Půjčíme si klíč.) 18. Odpojíme z s i+1 nejmenší klíč m a nejlevějšío sna l. 19. K vrcolu s i připojíme jako poslední klíč i a jako nejpravějšío sna l. 20. i m 21. Jinak: (Slučujeme sn.) 22. Vtvoříme nový vrcol s, který bude obsaovat všecn klíče a sn z vrcolů s i a s i+1 a mezi nimi klíč i. 23. Z vrcolu v odstraníme klíč i a sn s i a s i+1. Tto sn zrušíme a na jejic místo připojíme sna s. 24. Jinak provedeme krok 17 až 23 zrcadlově pro levéo bratra s i 1 místo s i+1. Časová složitost Pro rozbor časové složitosti předpokládáme, že parametr a a b jsou konstant. Hledání, vkládání i mazání proto tráví na každé ladině stromu čas O(1) a jelikož můžeme počet ladin odadnout jako Θ(log n), celková časová složitost všec tří základníc operací činí Θ(log n). Vraťme se nní k volbě parametrů a, b. Především je známo, že se nevplácí volit b výrazně větší než je dolní mez 2a 1 (detail viz cvičení 1). Proto se obvkle používají (a, 2a 1)-strom, případně (a, 2a)-strom. Rozdíl mezi b = 2a 1 a b = 2a se zdá být zcela nepodstatný, ale jak je vidět v cvičeníc 5 a 6, o jedničku větší manévrovací prostor má zásadní vliv na amortizovanou složitost. Pokud cceme datovou strukturu udržovat v klasické paměti, vplácí se volit a co nejnižší. Vodné parametr jsou například (2, 3) nebo (2, 4). Ukládáme-li data na disk, nabízí se vužít too, že je rozdělen na blok. Přečíst celý blok je přitom zruba stejně rclé jako přečíst jediný bte, zatímco skok na jiný blok trvá dlouo. Proto nastavíme a tak, ab jeden vrcol stromu zabíral celý blok. Například pro disk s 4 KB blok, 32-bitové klíče a 32-bitové ukazatele zvolíme (256, 511)-strom. Strom pak bude opravdu mělký: čtři ladin postačí pro uložení více než 33 milionů klíčů. Navíc na poslední ladině jsou pouze list, takže při každém ledání přečteme poué tři blok. V dnešníc počitačíc často mezi procesorem a lavní pamětí leží cace (rclá vrovnávací paměť), která má také blokovou strukturu s tpickou velikostí bloku 64 B. Často se proto i u stromů v lavní paměti volit trocu větší vrcol, ab 16 2016-01-25

odpovídal blokům cace. Pro 32-bitové klíče a 32-bitové ukazatele ted použijeme (4, 7)-strom. Jen si musíme dávat pozor na správné zarovnání adres vrcolů na násobk 64 B. Další variant Ve světě se lze setkat i s jinými definicemi (a, b)-stromů, než je ta naše. Často se například dělá to, že data jsou uložena pouze ve vrcolec na drué nejnižší ladině, zatímco ostatní ladin obsaují pouze pomocné klíče, tpick minima z podstromů. Tím si trocu zjednodušíme operace (viz cvičení 3), ale zaplatíme za to všší redundancí dat. Může to nicméně být šikovné, pokud potřebujeme implementovat slovník, který klíčům přiřazuje rozměrná data. V teorii databází a souborovýc sstémů se často ovoří o B-stromec. Pod tímto názvem se skrývají různé datové struktur, většinou (a, 2a 1)-strom nebo (a, 2a)-strom, nezřídka v úpravě dle předcozío odstavce. Cvičení 1. Odalte, jak závisí složitost operací s (a, b)-strom na parametrec a a b. Z too odvoďte, že se nikd nevplatí volit b výrazně větší než 2a. 2*. Naprogramujte (a, b)-strom a změřte, jak jsou na vašem počítači rclé pro různé volb a a b. Projevuje se vliv cace tak, jak jsme naznačili? 3. Rozmslete, jak provádět operace Insert a Delete na variantě (a, b)-stromů, která ukládá užitečná data jen do nejnižšíc vnitřníc vrcolů. nalzujte časovou složitost a srovnejte s naší verzí struktur. 4. Ukažte, že pokud budeme do prázdnéo stromu postupně vkládat klíče 1,..., n, provedeme celkem Θ(n) operací. K tomu potřebujeme pamatovat si, ve kterém vrcolu skončil předcozí vložený klíč, abcom nemuseli pokaždé ledat znovu od kořene. 5. Někd se odí minimalizovat vedle časové složitosti také počet strukturálníc změn stromu běem operace. Tak se říká změnám klíčů a ukazatelů uloženýc ve vrcolec. Ukažte, že pokud v původně prázdném (2, 3)-stromu provedeme n operací Insert, každá z nic provede amortizovaně konstantní počet strukturálníc změn. Zobecněte pro libovolné (a, b)-strom. 6*. Podobně jako v předcozím cvičení budeme počítat strukturální změn, tentokrát pro (2, 4)-strom a libovolnou kombinaci operací Insert a Delete. Ukažte, že nadále jedna operace provede amortizovaně O(1) změn. Zobecněte na (a, 2a)- strom a ukažte, že v (a, 2a 1)-stromec nic takovéo neplatí. 1.4. Èerveno-èerné strom Nní se od obecnýc (a, b)-stromů vrátíme zpět ke stromům binárním. Ukážeme, jak překládat (2, 4)-strom na binární strom, čímž získáme další variantu BVS s logaritmickou loubkou a jednoducým vvažováním. Říká se jí červeno-černé 17 2016-01-25

strom (red-black trees, RB strom). M si je předvedeme v trocu neobvklé, ale příjemnější variantě navržené v roce 2008 R. Sedgewickem pod názvem left-leaning red-black trees (LLRB strom). Překlad bude fungovat tak, že každý vrcol (2, 4)-stromu naradíme konfigurací jednoo nebo více binárníc vrcolů. b blo možné rekonstruovat původní (2, 4)- strom, zavedeme barv ran: červené ran budou spojovat vrcol tvořící jednu konfiguraci, černé ran povedou mezi konfiguracemi, čili to budou ran původnío (2, 4)-stromu. Barvu ran si můžeme budeme pamatovat například v jejím spodním vrcolu. Strom přeložíme podle následujícío obrázku. Vrcolům (2, 4)-stromu budeme podle počtu snů říkat 2-vrcol, 3-vrcol a 4-vrcol. 2-vrcol zůstane sám sebou. 3-vrcol naradíme dvěma binárními vrcol, přičemž červená rana musí vžd vést doleva (to je ono LL v názvu LLRB stromů, obecné RB strom nic takovéo nepožadují, což situaci později dost zkomplikuje). 4-vrcol naradíme třešničkou ze tří binárníc vrcolů. z Pokud podle těcto pravidel transformujeme i definici (2, 4)-stromu, vznikne následující definice LLRB stromu. Definice: LLRB strom je binární vledávací strom s vnějšími vrcol, jeož ran jsou obarven červeně a černě. Přitom platí následující aiom: 1. Neeistují dvě červené ran bezprostředně nad sebou. 2. Jestliže z vrcolu vede dolů jediná červená rana, pak vede doleva. 3. List jsou vžd obarven černě. (To se odí, jelikož list jsou pouze virtuálni, takže do nic neumíme barvu ran uložit.) 4. Na každé cestě z kořene do listu je stejný počet černýc ran. Prvním dvěma aiomům budeme říkat červené, zblým dvěma černé. Pozorování: Z aiomů plne, že každá konfigurace pospojovaná červenými ranami vpadá jedním z uvedenýc způsobů. Proto je každý LLRB strom překladem nějakéo (2, 4)-stromu podle našic pravidel. Důsledek: Hloubka LLRB stromu s n klíči je Θ(log n). Důkaz: Hloubka (2, 4)-stromu s n klíči činí Θ(log n), překlad na LLRB strom počet ladin nesníží a nejvýše zdvojnásobí. Vvažovací operace Operace s LLRB strom se skládají ze dvou základníc úprav. Tou první je opět rotace, ale používáme ji pouze pro červené ran: Fi! Fi: Obrázek s příkladem překladu. 18 2016-01-25

Rotace červené ran zacovává nejen správné uspořádání klíčů ve vrcolec, ale i černé aiom. Platnost červenýc aiomů záleží na barvác okolníc ran, takže rotaci budeme muset používat opatrně. (Rotování černýc ran se výbáme, protože b navíc porušovalo i aiom 4.) Dále budeme používat ještě přebarvení 4-vrcolu. Dvojici červenýc ran tvořícíc 4-vrcol přebarvíme na černou, a naopak černou ranu vedoucí z 4-vrcolu naoru přebarvíme na červenou: z z Tato úprava odpovídá rozštěpení 4-vrcolu na dva 2-vrcol, přičemž prostřední klíč do nadřazenéo k-vrcolu. Černé aiom zůstanou zacován, ale může dojít k porušení červenýc aiomů o patro výše. Vkládání štěpením sora dolů Nní popíšeme, jak se do LLRB stromu vkládá. Půjdeme na to asi takto: místo pro nový vrcol budeme ledat obvklým zpusobem, ale kdkoliv cestou potkáme 4-vrcol, rovnou o rozštěpíme přebarvením. ž dorazíme do listu, připojíme místo něj nový vnitřní vrcol a ranu, po které jsme přišli, obarvíme červeně. Tím se nový klíč připojí k nadřazenému 2-vrcolu nebo 3-vrcolu. To zacovává černé aiom, ale průběžně jsme porušovali t červené, takže se budeme vracet zpět do kořene a rotacemi je opravovat. Nní podrobněji. Běem ledání sestupujeme z kořene dolů a udržujeme invariant, že aktuální vrcol není 4-vrcol. Jakmile na nějaký 4-vrcol narazíme, přebarvíme o. Tím se rozštěpí na dva 2-vrcol a prostřední klíč se stane součástí nadřazenéo k-vrcolu. Víme ovšem, že to nebl 4-vrcol, takže se z něj nní stane 3-vrcol nebo 4-vrcol. Jen možná bude nekorektně zakódovaný: 3-vrcol ve tvaru pravé odbočk nebo 4-vrcol se dvěma červenými ranami nad sebou: z z Nakonec nás ledání novéo klíče dovede do listu, což je místo, kam bcom klíč ctěli vložit. Nad námi leží 2-vrcol nebo 3-vrcol. List změníme na vnitřní 19 2016-01-25

vrcol s novým klíčem, pod něj pověsíme dva nové list připojené černými ranami, ranu do otce přebarvíme na červenou: p p Co se stane? Nový klíč leží na jediném místě, kde ležet může. Černé aiom jsme neporušili, červené jsme opět moli porušit vtvořením nekorektnío 3-vrcolu nebo 4-vrcolu o patro výše. Nní se začneme vracet zpět do kořene a přitom opravovat všecna porušení červenýc aiomů tak, ab černé aiom zůstal zacován. Kdkoliv pod aktuálním vrcolem leží levá černá rana a pravá červená, tak tuto ranu zrotujeme. Tím z nekorektnío 3-vrcolu uděláme korektní a nekorektnío 4-vrcolu uděláme takový nekorektní, jeož obě ran jsou levé. Poté otestujeme, zda pod aktuálním vrcolem leží levá červená rana do sna, který má také levou červenou ranu. Pokud ano, objevili jsme zbývající případ nekorektnío 4-vrcolu, který rotací jeo orní červené ran převedeme na korektní. ž dojdeme do kořene, struktura opět splňuje všecn aiom LLRB stromů. Následuje implementace v pseudokódu. Eterní vrcol ukládáme jako konstantu, barvu ran si pamatujeme v jejic spodním vrcolu. Procedura LlrbInsert Vstup: Kořen stromu v, vkládaný klíč 1. Pokud v =, skončíme a vrátíme nově vtvořený červený vrcol v s klíčem. 2. Pokud = k(v), skončíme (klíč se ve stromu již nacází). 3. Jsou-li l(v) i r(v) červené, přebarvíme l(v), r(v) i v. 4. Pokud < k(v), položíme l(v) LlrbInsert(l(v), ). 5. Pokud > k(v), položíme r(v) LlrbInsert(r(v), ). 6. Je-li l(v) černý a r(v) červený, rotujeme ranu (v, r(v)). 7. Je-li l(v) červený a l(l(v)) také červený, rotujeme ranu (v, l(v)). Výstup: Nový kořen v Vkládání štěpením zdola naoru Mazání FIXME FIXME Časová složitost FIXME 20 2016-01-25

Cvičení 1. Spočítejte přesně, jaká může být minimální a maimální loubka LLRB stromu s n klíči. 21 2016-01-25