22.09.2013 Views

Gebalanceerde Bomen

Gebalanceerde Bomen

Gebalanceerde Bomen

SHOW MORE
SHOW LESS

Create successful ePaper yourself

Turn your PDF publications into a flip-book with our unique Google optimized e-Paper software.

<strong>Gebalanceerde</strong> <strong>Bomen</strong><br />

algoritmen voor binaire bomen werken goed voor verschillende soorten<br />

toepassingen maar hun ‘worst case’ gedrag zorgt voor problemen<br />

balanceren is een techniek die ervoor zorgt dat het slechtste geval<br />

zich niet kan voordoen maar implementatie is niet eenvoudig<br />

1


Top-down 2-3-4 <strong>Bomen</strong><br />

om ‘worst cases’ te vermijden is flexibiliteit nodig in de datastructuren,<br />

we veronderstellen dat knopen meer dan 1 sleutel kunnen bevatten<br />

we laten 3-knopen en 4-knopen toe (die 2 en 3 sleutels kunnen bevatten)<br />

uit een 3-knoop komen 3 links: 1 naar alle records met sleutels kleiner<br />

dan beide knopen, 1 met alle records waarvan de sleutels tussen de 2<br />

knopen liggen en 1 met alle grotere sleutels<br />

uit een 4-knoop komen 4 links: een voor elk interval dat door de 3<br />

knopen gedefinieerd is<br />

2


Fig. 1 Een 2-3-4 boom.<br />

3


zoeken is eenvoudig<br />

bvb. zoeken naar G in de boom van Fig.1:<br />

volg de middenste link van de wortelknoop (G ligt tussen E en R);<br />

volg de linkse link in de volgende knoop (knoop met H, I en N) en<br />

beëindig het zoeken zonder succes<br />

4


nieuwe knoop toevoegen: na een niet succesvolle zoektocht de knoop<br />

inhaken; wanneer de zoektocht eindigt in een 2-knoop maken we er<br />

een 3-knoop van<br />

bvb. X toevoegen in Fig.1 door X (en een extra link) toe te voegen<br />

aan de knoop die S bevat<br />

analoog kan van een 3-knoop een 4-knoop gemaakt worden<br />

5


wat als er een nieuwe sleutel toegevoegd moet worden aan een 4knoop?<br />

bvb. G toevoegen aan de boom in Fig.1<br />

betere oplossing dan er een 5-knoop van te maken in Fig.2<br />

• splits de 4-knoop in 2 2-knopen en geef één van de sleutels door<br />

aan zijn ouder<br />

• voeg daarna de nieuwe sleutel toe<br />

6


Fig. 2 Toevoegen (van G) aan een 2-3-4 boom<br />

7


toevoegen van sleutels aan een boom:<br />

wanneer er een sleutel doorgegeven moet worden aan een ouder die<br />

al een 4-knoop is<br />

een methode kan zijn om ook de ouder te splitsen (maar de hogere<br />

niveaus kunnen ook 4-knopen zijn ...)<br />

een eenvoudiger methode zorgt ervoor dat geen enkele ouder van<br />

een knoop in de boom een 4-knoop is door alle 4-knopen te splitsen<br />

tijdens het afdalen in de boom<br />

8


Fig. 3 Constructie van een 2-3-4 boom voor de volledige verzameling<br />

sleutels (A S E A R C H I N G E X A M P L E)<br />

9


een 2-knoop verbonden met een 4-knoop wordt getransformeerd in<br />

een 3-knoop verbonden met 2 2-knopen<br />

een 3-knoop verbonden met een 4-knoop kan getransformeerd worden<br />

in een 4-knoop verbonden met 2 2-knopen<br />

splitsen werkt omdat niet enkel de sleutels maar ook de verwijzingen<br />

verplaatst kunnen worden<br />

voordeel: alle bewerkingen zijn lokale transformaties (zie Fig. 4)<br />

10


Fig. 4 Splitsen van 4-knopen.<br />

11


wanneer de wortel een 4-knoop wordt splitsen we hem in 3 2-knopen<br />

(we hoeven niet te wachten op de volgende invoeging omdat er geen<br />

probleem kan zijn met de ouder van de wortelknoop)<br />

enkel bij het splitsen van de wortelknoop komt er een niveau bij in de<br />

boom<br />

op die manier verkrijgen we een gebalanceerde boom<br />

12


Eig. 1 Tijdens zoeken in 2-3-4 bomen met N knopen worden niet<br />

meer dan lgN + 1 knopen bezocht.<br />

De afstand van de wortel tot elke externe knoop is immers dezelfde.<br />

13


Eig. 2 Invoegen in 2-3-4 bomen met N knopen vergt minder dan<br />

lgN + 1 keer splitsen van knopen in het slechtste geval en gemiddeld<br />

minder dan 1 knoop.<br />

In het slechtste geval zijn alle knopen op het pad van de invoeging<br />

4-knopen, die allemaal gesplitst moeten worden.<br />

14


Fig. 5 Grote 2-3-4 boom<br />

voorbeeld in Fig. 5: boom opgebouwd met een random permutatie<br />

van 95 elementen<br />

de boom bevat 9 4-knopen, waarvan er maar 1 niet op het laagste<br />

niveau zit<br />

15


Rood-zwarte bomen<br />

2-3-4 bomen kunnen als standaard bomen voorgesteld worden door 1<br />

extra bit per knoop te gebruiken<br />

we veronderstellen dat 3-knopen en 4-knopen kleine binaire bomen<br />

zijn die met ‘rode’ verbindingen samenhangen, de ‘zwarte’ verbindingen<br />

houden de 2-3-4 bomen samen (rode verbindingen zijn voorgesteld<br />

als dikke lijnen in Fig. 6)<br />

16


Fig. 6 Rood-zwart voorstelling van 3-knopen en 4-knopen<br />

17


een voorstelling van de boom in Fig. 3 (er zijn verschillende representaties<br />

mogelijk<br />

Fig. 7 Rood-zwarte boom<br />

18


de ‘schuinte’ van de 3-knopen heeft geen belang (Fig. 6)<br />

met een 2-3-4 boom komen verschillende rood-zwart bomen overeen<br />

eigenschappen:<br />

• er zijn nooit twee opeenvolgende rode verbindingen op een pad<br />

van de wortel naar een externe knoop<br />

• elk van die paden heeft een zelfde aantal zwarte verbindingen<br />

het is nog altijd mogelijk dat een pad (afwisselend rood-zwart) twee<br />

keer zo lang is als een ander (volledig zwart) maar de padlengtes zijn<br />

allemaal evenredig met logN.<br />

19


de positie van duplicaten is opmerkelijk (zie Fig.7)<br />

als we niet zouden toelaten dat duplicaten zich aan beide zijden van<br />

een knoop kunnen bevinden kan de boom sterk uit balans geraken<br />

wanneer er veel duplicaten zijn<br />

belangrijke eigenschap: de zoekprocedure voor standaard zoeken in<br />

binaire bomen werkt ongewijzigd (behalve in het geval van gedupliceerde<br />

sleutels; we kunnen niet alle knopen met een gegeven sleutel<br />

vinden door de zoekprocedure verder te zetten)<br />

20


kleuren implementeren door 1 bit veld toe te voegen aan elke knoop,<br />

(een 1 wanneer de link die naar de knoop wijst rood is, een 0 wanneer<br />

die zwart is); de zoekprocedure bekijkt dat veld nooit<br />

het balanceermechanisme veroorzaakt bijgevolg geen overlast<br />

het zoeken is efficiënter omdat de boom gebalanceerd is<br />

er is ook heel weinig overlast door de invoegprocedure (er moet alleen<br />

gehandeld worden als er een 4-knoop is)<br />

21


void Dict::insert(itemType v, infoType info)<br />

{<br />

x = head; p = head; g = head;<br />

while (x != z)<br />

{<br />

gg = g; g = p; p = x;<br />

x = (v < x-> key) ? x->l : x->r;<br />

if (x->l->b && x->r->b) split(v);<br />

}<br />

x = new node(v, info, 1, z, z);<br />

if (v < p->key) p->l = x; else p->r = x;<br />

split(v); head->r->b=black;<br />

}<br />

22


Fig. 8 Toevoegen (van Y) aan rood-zwarte boom van Fig. 7<br />

23


er is een transformatie nodig wanneer we tegenkomen:<br />

• een 2-knoop die met een 4-knoop verbonden is<br />

• een 3-knoop die met een 4-knoop verbonden is (3 verschillende<br />

mogelijkheden: Fig. 9 en Fig. 10)<br />

24


Fig. 9 Splitsen van 4-knopen met een kleurwissel<br />

25


Fig. 10 Splitsen van 4-knopen met een kleurwissel: er is rotatie nodig.<br />

26


wanneer in Fig. 8 de links y, c en gc verwijzen naar I, R en N, gebeurt<br />

de transformatie naar Fig. 11 door de veranderingen:<br />

c->l = gc->r;<br />

gc->r = c;<br />

y->r = gc<br />

er zijn 3 andere analoge gevallen: de 3-knoop kan anders georiënteerd<br />

zijn of kan zich aan de linkerkant van y bevinden (in beide oriëntaties)<br />

27


Fig. 11 Roteren van een 3-knoop in Fig. 8.<br />

28


om alle vier de gevallen te behandelen gebruiken we de zoeksleutel<br />

v om het relevante kind (c) en het relevante kleinkind (gc) terug te<br />

vinden (3-knopen worden alleen opnieuw georiënteerd wanneer het<br />

zoeken ons naar de bodem van de boom geleid heeft)<br />

eenvoudiger dan wanneer we niet enkel c en gc moeten onthouden<br />

maar ook of ze linkse of rechtse links zijn<br />

29


struct node *rotate(itemType v, struct node *y)<br />

{<br />

struct node *c, *gc;<br />

c = (v < y->key) ? y->l : y->r;<br />

if (v < c->key)<br />

{ gc = c->l; c->l = gc->r; gc->r = c; }<br />

else<br />

{ gc = c->r; c->r = gc->l; gc->l = c; }<br />

if (v < y->key) y->l = gc; else y->r = gc;<br />

return gc;<br />

}<br />

30


de functie brengt de link terug naar de top van de 3-knoop maar voert<br />

zelf de kleurwissel niet uit<br />

voor het derde geval van split (Fig. 10):<br />

• stel g rood<br />

• stel x gelijk aan rotate(v, gg)<br />

• stel x zwart<br />

hiermee is dit geval gereduceerd tot het tweede geval (waar de 3knoop<br />

goed georiënteerd was)<br />

31


voor het vierde geval (twee links georiënteerd in verschillende richtingen;<br />

Fig. 10):<br />

stel p gelijk aan rotate(v, g)<br />

de illegale 3-knoop bestaande uit 2 knopen waarnaar door p en x<br />

verwezen werd is anders georënteerd<br />

alle knopen hebben dezelfde kleur, er is geen kleurwissel nodig en we<br />

vervallen in het derde geval (leidt tot een dubbele rotatie)<br />

32


Fig. 12 Splitsen van een knoop in een rood-zwart boom.<br />

33


Fig. 12 demonstreert de uit te voeren split wanneer G wordt toegevoegd<br />

eerst is er een kleurwissel (split) om de 4-knoop die H, I en N bevat<br />

te splitsen<br />

daarna is er een dubbele rotatie nodig: eerst rond de boog tussen I<br />

en R, daarna rond de boog tussen E en I<br />

na deze wijzigingen kan G toegevoegd worden links van H (Fig 13)<br />

34


Fig. 13 Bouwen van een rood-zwarte boom.<br />

35


wanneer de wortel een 4-knoop is (invoegen in de eerste boom van<br />

Fig. 13 maakt de split procedure de wortel rood: dit komt overeen<br />

met het transformeren, samen met de dummy knoop erboven tot een<br />

3-knoop<br />

er is geen enkele reden om dat te doen; vandaar dat er een expliciet<br />

in de code staat de wortel zwart te houden<br />

36


void split(itemType v)<br />

{<br />

x->b = red; x->l->b = black; x->r->b = black;<br />

if (p->b)<br />

{<br />

g->b = red;<br />

if (vkey != vkey) p = rotate(v, g);<br />

x = rotate(v, gg);<br />

x->b = black;<br />

}<br />

}<br />

37


de split procedure zorgt ervoor dat alle kleuren correct zijn na de<br />

rotatie en plaatst x voldoende hoog in de boom om ervoor te zorgen<br />

dat we niet verloren lopen in de zoektocht na alle wijzigingen van de<br />

links<br />

38


de klasse declaratie voor rood-zwarte bomen is precies dezelfde als<br />

voor binaire zoekbomen, er is alleen een extra binair veld b in node<br />

de dummy knopen in de Dict constructor moeten op de volgende<br />

manier geïnitialiseerd worden:<br />

Dict(int max)<br />

{<br />

z = new node( 0, infoNIL, black, 0, 0);<br />

z->l = z; z->r = z;<br />

head = new node(itemMIN, 0, black, 0, z);<br />

}<br />

39


Fig. 14 Bouwen van een rood-zwarte boom.<br />

40


Eig.3 Zoeken in een rood-zwarte boom met N knopen opgebouwd<br />

met random sleutels heeft ongeveer lgN vergelijkingen nodig, en voor<br />

een invoeging is gemiddeld minder dan 1 rotatie nodig.<br />

Het is vooral voor het worst-case gedrag dat gebalanceerde bomen<br />

zo aantrekkelijk zijn.<br />

41


Fig. 15 Een rood-zwarte boom voor een ontaard geval (opgebouwd<br />

door de getallen 1 tot 95 in volgorde toe te voegen aan een lege<br />

boom).<br />

42


Eig.4 Zoeken in een rood-zwarte boom met N knopen vergt minder<br />

dan 2 lg N+2 vergelijkingen en een toevoeging vergt minder rotaties<br />

dan een kwart van de vergelijkingen.<br />

43


Andere algoritmen<br />

Er bestaan andere analoge strategieën voor het implementeren van<br />

gebalanceerde binaire bomen. Het is vooral de rotatie die de bomen<br />

balanceert.<br />

Oudste en best gekende gebalanceerde boom is de AVL boom. Die<br />

heeft de eigenschap dat de hoogte van de twee deelbomen van elke<br />

knoop ten hoogste met 1 verschilt. Wanneer deze voorwaarde overtreden<br />

wordt door het toevoegen van een knoop, dan kan er terug<br />

aan voldaan worden door te roteren.<br />

44


Een andere gekende structuur voor gebalanceerde bomen is de 2-3<br />

boom, waarin enkel 2- en 3-knopen toegelaten zijn. Toevoegen kan<br />

door het implementeren van een extra lus (voor rotaties) maar het is<br />

niet flexibel genoeg voor een goede top-down versie.<br />

45

Hooray! Your file is uploaded and ready to be published.

Saved successfully!

Ooh no, something went wrong!