Upload
phungquynh
View
219
Download
2
Embed Size (px)
Citation preview
Iskalna drevesaTako staticne kot dinamicne simbolov tabele lahko predstavimo vurejenem drevesu.Osnovno vodiloV vsakem od vozlisc drevesa moramo imeti iz podatkov, ki soshranjeni v vozliscu, moznost ugotoviti, v katero smer je trebanadaljevati iskanje, ce ze nismo na cilju. To je mogoce le, ce sosimboli v poddrevesih vozlisca razmejeni s kljuci v vozliscu. Najima vozlisce v poddrevesa
D1,D2, . . . ,Dm.
Za razmejitev potrebujemo m − 1 kljucev. Naj S (D) oznacujemnozico simbolov v drevesu D. Ce oznacimo zv .ime1, v .ime2, . . . v .imem−1 simbole, s katerimi v vozliscu vrazmejujemo poddrevesa, je naravna razmejitev kar
S (D1) ≤ v .ime1 < S (D2) ≤ · · · ≤ v .imem−1 < S (Dm) .
J.Kozak: PSA I, 2010-2011 1 / 57
Preprosto dvojisko iskalno drevo
V drevo vstavljamo le simbole, nic dodatnih podatkov. Ker jedrevo dvojisko, v vsakem od vozlisc potrebujemo le en kljuc, ki locisimbole poddreves. Ta kljuc je hkrati tudi simbol, ki smo ga vvozlisce vstavili.Vozlisce
ime . . . simbol v vozlisculevi . . . kazalec na levo poddrevodesni . . . kazalec na desno poddrevo
V iskanju ucinkovitih predstavitev se omejimo le na operaciji vstaviin obstaja, ki ju zdruzimo v enotno proceduro poi s c i in vstavi .Preprost algoritem poi s c i in vstavi drevo pri tem dogovoru preiscedrevo z bisekcijo. Ce imena ne najde, na primerno mesto vstavinovo vozlisce in pripadajoce ime.
J.Kozak: PSA I, 2010-2011 2 / 57
procedure poi s c i in vstavi(koren, x , i , obstaja);
{ Poisce x v iskalnem drevesu. Ce ga najde, je i kazalec navozlisce, za katero je i .ime = x , in obstaja = true,sicer pa vstavi x na mesto, kamor sodi.Tedaj i kaze na vstavljeno vozlisce in obstajavrne vrednost false. Podatek koren kaze na koren drevesa. }
begini := koren;
ocei := 0;
while i 6= 0 docase
x < i .ime : begin ocei := i ; i := i .levi endx = i .ime : begin obstaja := true; exit(poi s c i in vstavi) endx > i .ime : begin ocei := i ; i := i .desni end
end;J.Kozak: PSA I, 2010-2011 3 / 57
{ x ni v drevesu. }obstaja := false;
novovozli s ce(i);
i .ime := x ; i .levi := 0; i .desni := 0;
casekoren = 0 : koren := i ;x < ocei .ime : ocei .levi := i ;x > ocei .ime : ocei .desni := i ;
endend.
Analiza zahtevnostiCasovna zahtevnost v najboljsem primeru: O (log n)
Casovna zahtevnost v najslabsem primeru: O (n). Zgled sobesedila, urejena po abecednem vrstnem redu in zaporedjebesedil: A, B, C, . . .
J.Kozak: PSA I, 2010-2011 4 / 57
AVL drevo
Prva dobra ideja: AVL drevo, po avtorjih G.M. Adelson-Velsky,E.M. Landis(1962). Je po globini uravnotezeno iskalno dvojiskodrevo. Naj globina(D) oznaci globino drevesa D.
Definicija AVL drevesaAVL drevo D je, ali prazno ali pa dvojisko drevo, za katerega zalevo in desno poddrevo DL,DD korena velja, da sta obe AVLdrevesi in se njuni globini razlikujeta kvecjemu za 1,
|globina (DL)− globina (DD)| ≤ 1.
J.Kozak: PSA I, 2010-2011 5 / 57
Globina AVL drevesa
IzrekGlobina AVL drevesa z n simboli je v najslabsem primeru O (log n).
Dokaz.Vpeljemo N(h) := najmanjse mozno stevilo vozlisc AVLdrevesu globine hOcitno velja N(h) = N(h − 1) + N(h − 2) + 1, h ≥ 2,in N(1) = 1,N(2) = 2.
Zaporedje N(h) je blizu Fibonaccijevem. Torejϕh := N(h) + 1 in dobimo ϕh = ϕh−1 + ϕh−2,ϕ1 = 2, ϕ2 = 3.
Lagrangeev nastavek ϕh = λh pove, da mora λ zadoscati enacbi
λ2 − λ− 1 = 0, λ∓ =12
(1∓√
5).
J.Kozak: PSA I, 2010-2011 6 / 57
Odtod splosna resitev
ϕh = c1
(12
(1−√
5))h
+ c2
(12
(1 +√
5))h
≈ c1(−0.618034)h + c2(1.61803)h
Iz robnih pogojev ϕ1 = 2, ϕ2 = 3 sledic1 = 1
10
(5− 3
√5)≈ −0.17082,
c2 = 110
(5 + 3
√5)≈ 1.17082.
Torej je
ϕh = N(h) + 1 ≈ c2
(12
(1 +√
5))h
inh = O (log n) .
J.Kozak: PSA I, 2010-2011 7 / 57
Implementacija AVL drevesa
Vozlisce v AVL drevesuime . . . simbol, ki ga hranimo v vozliscu,f . . . faktor ravnotezja, razlika med globino levega in desnegapoddrevesa,levi . . . kazalec na koren levega poddrevesa,desni . . . kazalec na koren desnega poddrevesa,
J.Kozak: PSA I, 2010-2011 8 / 57
Popravki strukture AVL drevesa
Naj bo v vozlisce, ki je najglobje med tistimi s nedovoljenimfaktorjem ravnotezja po vstavljanju simbola s.
Rotacije ali popravki AVL drevesaLL . . . od vozlisca v smo pri vstavljanju krenili dvakrat v levo,LD . . . od vozlisca v smo pri vstavljanju krenili v levo, nato vdesno,DD . . . od vozlisca v smo pri vstavljanju krenili dvakrat vdesno,DL . . . od vozlisca v smo pri vstavljanju krenili v desno, nato vlevo.
J.Kozak: PSA I, 2010-2011 9 / 57
procedure poi s c i in vstavi AVL(koren, x , i , obstaja);{ Poisce x v AVL drevesu s korenom koren. Kot rezultat v tej
spremenljivki vrnemo novi koren drevesa, ce se je ta spremenil.Ce ime x najde, je i oznaka vozlisca,za katero je i .ime = x in obstaja=true, drugace pavstavi x na pripadajoce mesto. i tedaj kaze na vstavljenovozlisce in obstaja dobi vrednost false. V kolikor se zvstavljanjem ravnotezje porusi, procedura izvrsi potrebnorotacijo, tako da tudi novo drevo ostaja uravnotezeno. }
beginif koren = 0 then begin{ Drevo je se prazno. }obstaja := false;novovozli s ce(i);koren := i ;i .ime := x ; i .f := 0; i .levi := 0; i .desni := 0;exit(poi s c i in vstavi AVL)
end;J.Kozak: PSA I, 2010-2011 10 / 57
{ Drevo ze obstaja. Poiscemo mesto v drevesu, kamor sodisimbol x . Pri tem spremljamo najblizjega prednika, prikaterem se lahko porusi ravnotezje. Pomenspremenljivk je
k := tekoce vozlisce, ki ga pregledujemo,ocek := oce vozlisca k,v := najblizji prednik, pri katerem se lahko porusi ravnotezje,ocev := oce vozlisca v . }
k := koren;
ocek := 0;
v := koren;
ocev := 0;
J.Kozak: PSA I, 2010-2011 11 / 57
while k 6= 0 do beginif k.f 6= 0 then begin { Najglobji kandidat za rotacije }
ocev := ocek; v := k;
end;if x < k.ime then begin {x je lahko le v levem poddrevesu}
ocek := k; k := k.levi ;endelseif x > k.ime then begin {x je lahko le v desnem poddrevesu}
ocek := k; k := k.desni ;endelse begin
obstaja := true; i := k;
exit(poi s c i in vstavi AVL);
end ;
end ;J.Kozak: PSA I, 2010-2011 12 / 57
{ Simbola x se ni v drevesu. }obstaja := false; novovozli s ce(i);i .ime := x ; i .f := 0; i .levi := 0; i .desni := 0;{ Vstavimo novo vozlisce i kot sina lista ocek. }if x < ocek.ime then
ocek.levi := ielse
ocek.desni := i ;{ Popravimo faktorje ravnotezja na poti od v do ocek.
Vsi ti faktorji so prvotno vrednosti 0 po izbiri vozlisca v .Spremenljivka ∆f oznaci, v katero poddrevo v -ja smovstavili simbol x . vt je kandidat za koren po rotaciji v v . }
if x > v .ime then begin { vd koren poddrevesa }k := v .desni ; vt := vd := k; ∆f := −1;
endelse begin { vl koren poddrevesa, kamor smo krenili.}
k := v .levi ; vt := vl := k; ∆f := 1;end ;
J.Kozak: PSA I, 2010-2011 13 / 57
while k 6= i doif x > k.ime then begin{ Ko smo iskali simbol x , smo tu zavili v desno. }k.f := −1; k := k.desni
endelse begin{ Ko smo iskali simbol x , smo tu zavili v levo. }k.f := 1; k := k.levi
end;
{ Vozlisca v se nismo pregledali. }if |v .f + ∆f | ≤ 1 then begin{ Drevo je uravnotezeno. }v .f := v .f + ∆f ;
exit(poi s c i in vstavi AVL)
end;J.Kozak: PSA I, 2010-2011 14 / 57
{ Drevo je neuravnotezeno. }if ∆f = 1 then begin{ Levo poddrevo je vecje globine kot desno.
Uporabimo rotaciji LL ali LD. }if vl .f = 1 then begin { Rotacija LL. }
v .levi := vl .desni ;vl .desni := v ;
v .f := 0;
vl .f := 0endelse begin { Rotacija LD. }
vld := vl .desni ;vldl := vld .levi ;vldd := vld .desni ;
J.Kozak: PSA I, 2010-2011 15 / 57
{ Rotacija }vl .desni := vldl ;v .levi := vldd ;
vld .levi := vl ;vld .desni := v ;
{ Dolocimo faktorje ravnotezja v v , vl in vld .}case
vld .f = 1 : begin v .f := −1; vl .f := 0; end;
vld .f = −1 : begin v .f := 0; vl .f := 1; end;
vld .f = 0 : begin v .f := 0; vl .f := 0; end;
end;
vld .f := 0;
vt := vld ;
endend { Rotaciji LL in LD zakljuceni }
J.Kozak: PSA I, 2010-2011 16 / 57
else begin{ Na tem mestu je ∆f = −1. Desno poddrevo je globje.
Opraviti je treba rotaciji DD, DL, ki sta zrcalni k LL, LD. }end;
{ Popravimo se oceta vozlisca v , katero smo ga zrcaliliv globino. Na njegovem mestu je sedaj vozlisce vt. }if ocev = 0 then
koren := vtelse
if ocev .levi = v then ocev .levi := vt else ocev .desni := vt;
end.
J.Kozak: PSA I, 2010-2011 17 / 57
Rdece-crno drevoRdece-crno drevo je iskalno dvojisko drevo, uravnotezeno po steviluvozlisc crne barve na poti od vozlisca do vseh listov - potomcev. Vprimerjavi z AVL drevesi v vozliscih dodatno vodimo barvo inkazalec na oceta, ne potrebujemo pa faktorja ravnotezja.Uravnotezenost, ki jo zahtevamo tu, je bolj ohlapna, zatopricakujemo manj popravkov pri vstavljanju ali brisanju simbolov.Rdece-crna drevesa pogosto uporabljamo tudi kot sestavni delzapletenejsih podatkovnih struktur.Definicija rdece-crnega drevesaRdece-crno drevo je iskalno dvojisko drevo, za katerega velja
vsako vozlisce je crne ali rdece barve,koren drevesa (po definiciji tudi koren praznega drevesa) jecrne barve,ce je vozlisce rdece, sta oba sinova crna,za vsako vozlisce v velja, da je enako stevilo crnih vozlisc napoti od vozlisca do vsakega lista, ki je potomec v .
J.Kozak: PSA I, 2010-2011 18 / 57
Sestava vozlisca rdece-crnega drevesa:ime . . . simbol, ki ga v vozliscu hranimo,barva. . . crna ali rdeca,oce . . . kazalec na oceta,levi . . . kazalec na levo poddrevo,desni . . . kazalec na desno poddrevo.
Kaj nam zagotavljajo lastnosti rdece-crnega dreves? Naj bo Tnrdece-crno drevo z n simboli. Vpeljimo crno globino vozliscav ∈ Tn zcg(v) := 1+ stevilo crnih vozlisc na poti od v do lista-potomca.Vozlisca v samega v cg ne stejemo. Za prazno drevo definiramocg kot 0. Crna globina je ocitno dobro definirana.IzrekZa rdece-crno drevo Tn z n simboli velja
globina(Tn) ≤ 2 dlog2 (n + 1)e .J.Kozak: PSA I, 2010-2011 19 / 57
Dokaz. Najprej pokazimo, da ima vsako poddrevo s korenomv ∈ Tn vsaj 2cg(v) − 1 vozlisc. Z indukcijo po stevilu vozlisc n vdrevesu. Ce je v prazno drevo, je n = 0 in cg(v) = 0 ter20 − 1 = 0 ≥ 0. Trditev izreka torej velja. Naj velja sedaj trditev zaoba sinova vozlisca v , ki imata kvecjemu n − 1 vozlisc. Ce je sin vrdec, zanj velja cg(sin(v)) = cg(v), sicer cg(sin(v)) = cg(v)− 1.Po induktivni predpostavki je torej je v drevesu s korenom v vsaj
1 + 2(
2cg(v)−1 − 1)
= 2cg(v) − 1
vozlisc, kar dokazuje prvo trditev. Ker vsaka pot od korena drevesado lista vsebuje vsaj pol crnih listov, je
cg(koren) ≥ 12h, h := globina(Tn),
inn ≥ 2cg(koren) − 1 ≥ 2
12 h − 1.
J.Kozak: PSA I, 2010-2011 20 / 57
Prazno vozlisce
Operacije nad rdece-crnim drevesom se poenostavijo, ce praznadrevesa nadomestimo s strazarjem, ki mu recemo prazno vozlisce.Na prazno vozlisce kazejo vsi kazalci v prazno, tudi oce v korenu.
Spremenljivke v praznem vozliscuime . . . simbol v vozliscu, karkoli,barva = crna,oce . . . kazalec na oceta, karkolilevi . . . kazalec na levo poddrevo, karkolidesni . . . kazalec na desno poddrevo, karkoli.
Ker prazno nadomesca prazna drevesa, je njegova crna globina podefiniciji enaka 0.
J.Kozak: PSA I, 2010-2011 21 / 57
procedure rotacijavlevo(koren, prazno, v);{ Opravi levo rotacijo rdece-crnem drevesu s korenom koren in
strazarjem prazno. Vozlisce v in desni sin vd zamenjata mesti,tako da je po rotaciji v levi sin vd . Urejenost simbolov se ohrani.}
beginvd := v .desni ;v .desni := vd .levi ;if vd .levi 6= prazno then vd .levi .oce := v ;vd .oce := v .oce;if v .oce = prazno then
koren := vdelse
if v = v .oce.levi thenv .oce.levi := vd
elsev .oce.desni := vd ;
vd .levi := v ; v .oce := vd ;end;
J.Kozak: PSA I, 2010-2011 22 / 57
procedure poi s c i in vstavi RC(koren, prazno, x , v , obstaja);
{ Poisce x v rdece-crnem drevesu s korenom koren in strazarjemprazno. Kot rezultat v koren vrne nov koren drevesa,ce se je ta spremenil. Ce ime x najde, je v kazalec na vozlisce,za katero je v .ime = x in obstaja = true, drugace pavstavi x na pripadajoce mesto. v tedaj kaze na vstavljenovozlisce in obstaja dobi vrednost false. V kolikor se zvstavljanjem ravnotezje porusi, procedura opravi potrebenpopravek, tako da tudi novo drevo ostaja rdece-crno. }
beginocev := prazno;
v := koren;
while v 6= prazno do beginif x = v .ime then begin
obstaja := true;
exit(poi s c i in vstavi RC);
end;J.Kozak: PSA I, 2010-2011 23 / 57
{ Simbola x ni v vozliscu v . Opravimo korak v globino. }ocev := v ;
if x < v .ime thenv := v .levi { Iscemo v levo. }
elsev := v .desni ; { Iscemo v desno. }
end;
{ Trenutno vozlisce v kaze v prazno. Simbola x se ni v drevesu. }obstaja := false;
novovozli s ce(v);
v .oce := ocev ;
J.Kozak: PSA I, 2010-2011 24 / 57
if ocev = prazno thenkoren := v ;
elseif v .ime < ocev .ime then
ocev .levi := velse
ocev .desni := v ;
v .levi := prazno;
v .desni := prazno;
v .barva := rdeca;
{ Vstavljanje je zakljuceno. Opravimo sepotrebne spremembe barv vozlisc in rotacije. }
rdece − crni popravki(koren, prazno, v);
end;
J.Kozak: PSA I, 2010-2011 25 / 57
Mozne prepovedane situacije
Spremenljivkev . . . rdece vozlisce, v katerega smo vstavili nov simbolz . . . trenutno rdece vozlisce, katerega oce je morda rdec. Ceje z .oce rdec, je potreben popravekstricz . . . stric vozlisca z
Situacijez .oce je rdec in levi sin, stricz je rdec, z je rdec in levi alidesni sinz .oce je rdec in levi sin, stricz je crn, z je rdec in desni sinz .oce je rdec in levi sin, stricz je crn, z je rdec in levi sinz .oce je rdec in desni sin, stricz je rdec, z je rdec in levi alidesni sinz .oce je rdec in desni sin, stricz je crn, z je rdec in desni sinz .oce je rdec in desni sin, stricz je crn, z je rdec in levi sin
J.Kozak: PSA I, 2010-2011 26 / 57
procedure rdece − crni popravki(koren, prazno, v);
{ Procedura popravi drevo s korenom koren in strazarjem prazno,da bo res rdece-crno. Vozlisce v je list, kamor smo vstavilisimbol in je rdec. Pred vstavljanjem je bilo drevo rdece-crno. }
beginz := v ; { Trenutno, rdece vozlisce. }while z .oce.barva = rdeca do begin{ Tudi z .oce je rdec. Drevo je treba popraviti. }if z .oce = z .oce.oce.levi then begin{ z .oce je levi sin starega oceta z .oce.oce. }stricz := z .oce.oce.desni ;if stricz .barva = rdeca then begin
z .oce.barva := crna;
stricz .barva := crna;
z .oce.oce.barva := rdeca;
z := z .oce.oce;
endJ.Kozak: PSA I, 2010-2011 27 / 57
else beginif z = z .oce.desni then begin
z := z .oce;
rotacijavlevo(koren, prazno, z);
end;
z .oce.barva := crna;
z .oce.oce.barva := rdeca;
rotacijavdesno(koren, prazno, z .oce.oce);
endend { Primer, ko je z.oce levi sin, je zakljucen. }else begin{ z .oce je desni sin starega oceta z .oce.oce, stricz levi.
Enako kot v prvem delu, le z desni in levi zamenjano. }end;
end;
koren.barva := crna;
end;J.Kozak: PSA I, 2010-2011 28 / 57
function naslednik(v);{ Funkcija poisce naslednika vozlisca v ∈ T pri pregledu
nepraznega dvojiskega drevesa T v vmesnem vrstnem redu. }begin{ Ce je desno poddrevo v neprazno, je to
najgloblje vozlisce v najbolj levi veji tega poddrevesa. }if v .desni 6= 0 then begin
vn := v .desni ; while vn.levi 6= 0 do vn := vn.levi ;return(vn);
end;{ Desno poddrevo v je prazno. Naslednik je najblizji prednik v ,
ki ima vozlisce v levemu poddrevesu. }vn := v .oce;while vn 6= 0 and v = vn.desni do begin
v := vn; vn := vn.oce;end;return(vn);
end;J.Kozak: PSA I, 2010-2011 29 / 57
procedure odstrani(koren, prazno, v);
{ Procedura odstrani vozlisce v iz rdece-crnega drevesa skorenom koren in strazarjem prazno. Ce se koren pri brisanjuspremeni, ga popravi. }
begin{ y naj bo kazalec na vozlisce, ki bo dejansko odstranjeno. }if v .levi = prazno or v .desni = prazno then
y := velse
y := naslednik(v);
{ x naj bo neprazni sin y , ce obstaja. }if y .levi 6= prazno then
x := y .levielse
x := y .desni ;J.Kozak: PSA I, 2010-2011 30 / 57
{ Tudi ce je x = sin(y) strazar prazno, je prireditev korektna. }x .oce := y .oce;
if y .oce = prazno thenkoren := x
elseif y = y .oce.levi then
y .oce.levi := xelse
y .oce.desni := x ;
if y 6= v then v .ime := y .ime;
if y .barva = crna thenrdece − crni popravki po brisanju(koren, prazno, x);
sprosti(y); { Vrnemo prostor y v ponovno uporabo. }end;
J.Kozak: PSA I, 2010-2011 31 / 57
Analiza odstranjenega vozlisca y
Mozni izidiy .barva = rdeca, drevo ostaja rdece-crno, popravki nisopotrebniy .barva = crna, y je stari koren in njegov rdeci sin postanekoren. Nobena od crnih globin se ni spremenila, le barvakorena ni prava.y .barva = crna, y .oce in x = sin(y) sta bila oba rdeca.Rdece vozlisce y .oce ima po novem rdecega sina. Hkrati jeprekrsena tudi dogovorjena crna globina na poteh, ki so prejvodile skozi y .y .barva = crna, ko odstranimo y , ima lahko crna globina popoti, ki je vsebovala y , eno crno vozlisce premalo.
J.Kozak: PSA I, 2010-2011 32 / 57
Mozne prepovedane situacijePopravek klicemo le, ce je y .barva = crna. Na zacetku jex = sin(y), edini sin vozlisca y , ki smo ga odstranili ali strazar.
Spremenljivkex . . . trenutno vozliscew . . . brat vozlisca x , procedura analizira podrobno lemoznost, ko je w desni brat x
Popravljamo od zacetnega x = sin(y). Predpostavka je, da je vpoteh od oceta x .oce = w .oce preko x crna globina za eno manjsakot preko brata w .Situacije, le v primeru, ko je x levi sin. Druga moznost sledi posimetriji.
x -ov brat w je rdecx -ov brat w je crn in oba njegova sinova tudilevi sin w je rdec, desni sin w je crnlevi sin w je crn, desni sin w je rdec
J.Kozak: PSA I, 2010-2011 33 / 57
procedure rdece − crni popravki po brisanju(koren, prazno, v);{ Procedura popravi drevo s korenom koren in strazarjem prazno,
da bo res rdece-crno. Vozlisce v je vozlisce, kjer jemorda potreben popravek in je sin vozlisca, ki je bilo odstranjeno.Proceduro klicemo le, ce je bilo odstranjeno vozlisce crno. }
beginx := v ; { x je trenutno vozlisce. }while x 6= koren and x .barva = crna do begin
if x = x .oce.levi then begin{ x je levi sin }w := x .oce.desni ; { Desni brat x . }if w .barva = rdeca then begin{ Popravek 1: brat w je rdec, sinova w morata biti crna. }w .barva := crna;x .oce.barva := rdeca;rotacijavlevo(koren, prazno, x .oce);w := x .oce.desni ; { Novi desni, crni brat. }
end;J.Kozak: PSA I, 2010-2011 34 / 57
if w .levi .barva = crna and w .desni .barva = crna then begin{ Popravek 2: brat w je crn in oba njegova sinova
sta crna. }w .barva := rdeca;
x := x .oce;
endelse begin
if w .desni .barva = crna then begin{ Popravek 3: brat w je crn in ima levega sina rdecega
in desnega crnega. }w .levi .barva := crna;
w .barva := rdeca;
rotacijavvdesno(koren, prazno,w);
w := x .oce.desni ;end;
J.Kozak: PSA I, 2010-2011 35 / 57
{ Popravek 4: brat w je crn in njegov desni sin tudi. }w .barva := x .oce.barva;
x .oce.barva := crna;
w .desni .barva := crna;
rotacijavlevo(koren, prazno, x .oce);
x := koren; { Prekinemo zanko. }end
endelse begin{ x je desni sin, enako kot v primeru x je levi sin,
le z ”levi” in ”desni” zamenjano. }end;
end;
x .barva := crna;
end;J.Kozak: PSA I, 2010-2011 36 / 57
2-3 drevo
2-3 drevo (J. E. Hopcroft) je dvojisko drevo, uravnotezeno postopnji vozlisc in nivoju listov. Je predhodnik 2-3-4 dreves insplosneje, B-dreves. Na 2-3 drevesu najpreprosteje spoznamoosnovne karakteristike te pomembne veje dreves.
Definicija 2-3 drevesa2-3 drevo je dvojisko drevo, za katerega velja
vsako vozlisce je stopnje kvecjemu 3,vsako vozlisce, z izjemo korena in listov, je stopnje vsaj 2,vsi listi so na istem nivoju, globini 2-3 drevesa.
Uporaba 2-3 drevesakot iskalno drevo, posplositve so razlicne izpeljanke B-dreveskot vrsta s prednostjo, razsirjena z operacijo unija
J.Kozak: PSA I, 2010-2011 37 / 57
Kaj zagotavljajo lastnosti 2-3 dreves?2-3 drevo raste v globino kvecjemu tako hitro kot poravnanodvojisko drevo v enakim stevilom vozlisc2-3 drevo raste v globino vsaj tako hitro kot poravnanotrojisko drevo v enakim stevilom vozlisc
IzrekZa 2-3 drevo Tn z n ≥ 3 vozlisci velja
dlog3 (2n + 1)e ≤ globina(Tn) ≤ dlog2 (n + 1)e .
Dokaz. Zgornjo mejo ze poznamo. Polno trojisko drevo globine hima
n = 1 + 3 + · · ·+ 3h−1 =3h − 13− 1
vozlisc, torej je njegova globina enaka
h = log3 (2n + 1)
in globina poravnanega trojiskega drevesa dlog3 (2n + 1)e.J.Kozak: PSA I, 2010-2011 38 / 57
Iskalna 2-3 drevesa
Osnovne izpeljankev notranjih vozliscih hranimo le kljuce, v listih kljuce inpripadajoce dodatne podatke. Posplositev: B-drevesa.v notranjih vozliscih hranimo kljuce in pripadajoce dodatnepodatke (ali kazalce nanje). Posplositev: B+-drevesa.
Za zgled si poglejmo prvi podrazred 2-3 dreves. Vse dodatnepodatke, ki pripadajo danemu kljucu, hranimo v listih. Kotposledica torej podatki v listih sestavljajo tabelo, linearno urejenopo kljucih z leve v desno.
J.Kozak: PSA I, 2010-2011 39 / 57
Sestava vozlisc prve vrste iskalnih 2-3 dreves:oce . . . kazalec na oceta,s . . . stopnja vozlisca,kljuc[i ], i = 1, . . . , s − 1 . . . kljuci, ki razmejujejo poddrevesa;tabela kljuc je velikosti s − 1 ≤ 3,sin[i ], i = 1, . . . , s . . . kazalci na poddrevesa; tabela sin jevelikosti s ≤ 4.
Podatki v listih so lahko bistveno drugacni po naravi in obsegu kotv notranjih vozliscih. Tam nam je treba hraniti le kljuce, v listih patudi pripadajoce podatke ali kazalce do njih. To podrobnost zaradinazornosti prepustimo implementaciji.Osnovna ideja vzdrzevanja 2-3 dreves je: ce po vstavljanju stopnjavozlisca naraste na 4, ga razcepimo in popravljamo navzgor, ce jese potrebno.
J.Kozak: PSA I, 2010-2011 40 / 57
procedure preuredi(v , koren);
{ Drevo s korenom koren je 2-3 drevo. Edina izjema je mordanotranje vozlisce v , ki je lahko tudi stopnje 4. Procedura topopravi in vrne nov koren, ce se je koren drevesa pri preurejanjuspremenil. Procedura predpostavlja tudi, da imajo kljuciv notranjih vozliscih ze prave vrednosti, torej najvecjovrednost kljuca v pripadajocem poddrevesu. }
beginif v .s ≤ 3 then exit(preuredi);
{ Stopnja v je 4, drevo se ni 2-3 drevo. }novovozli s ce(w); { Novo vozlisce w bo desni brat v . }w .s := 2; v .s := 2;
w .kljuc[1] := v .kljuc[3];
w .kljuc[2] := v .kljuc[4];
w .sin[1] := v .sin[3];
w .sin[2] := v .sin[4];J.Kozak: PSA I, 2010-2011 41 / 57
if v .oce = 0 then begin{ Vozlisce v je koren, v = koren.
Generiramo nov koren in s tem poglobimo drevo. }novovozli s ce(koren);
koren.s := 2;
koren.kljuc[1] := v .kljuc[2];
koren.kljuc[2] := w .kljuc[2];
koren.sin[1] := v ;
koren.sin[2] := w ;
v .oce := koren;
w .oce := koren;
endelse begin{ Vozlisce v ni koren. Vstavimo w v oceta v .oce desno od v . }
J.Kozak: PSA I, 2010-2011 42 / 57
i := 1;
{ Kateri zaporedni sin svojega oceta je v? }while v .oce.sin[i ] 6= v do i := i + 1;
for j := v .oce.s downto i + 1 do beginv .oce.sin[j + 1] := v .oce.sin[j];v .oce.kljuc[j + 1] := v .oce.kljuc[j];
end;
w .oce := v .oce;
v .oce.sin[i + 1] := w ;
v .oce.kljuc[i ] := v .kljuc[2];
v .oce.kljuc[i + 1] := w .kljuc[2];
v .oce.s := v .oce.s + 1;
v := v .oce;
preuredi(v , koren);
end;
end;J.Kozak: PSA I, 2010-2011 43 / 57
2-3 dreveso kot vrsta s prednostjo, razsirjena z unijo
Poleg operacij, ki jih pozna vrsta s prednostjo, dodamo seunija : (vrsta, vrsta)→ vrsta,
ki vrne vrsto s prednostjo, katera vsebuje podatke obehprvotnih vrst.Predstavitev s kopico ni primerna: unija je linearno casovnozahtevna.Vrsto s prednostjo lahko predstavimo tudi kot iskalno drevo,npr. AVL drevo, rdece-crno drevo, 2-3 drevo, a je potratno.Ni preprosto zdruziti dve AVL ali rdece-crni drevesi v drevoenake narave.Dve 2-3 drevesi (prve vrste) lahko zdruzimo v novo 2-3 drevo,ce liste obeh postavimo na isti nivo in koren plitvejsegaprilepimo k vozliscu, ki je v globjem za eno visje. Pri temseveda ne moremo vec ucinkovito zagotoviti, da bi bili kljuci vlistih linearno urejeni, a se vedno lahko v 2-3 drevesupredstavimo vrsto s prednostjo.
J.Kozak: PSA I, 2010-2011 44 / 57
Sestava vozlisc 2-3 drevesa za predstavitev vrste s prednostjo:oce . . . kazalec na oceta,s . . . stopnja vozlisca,max . . . najvecji podatek v poddrevesu danega vozlisca,sin[i ], i = 1, . . . , s . . . kazalci na poddrevesa; tabela sin jevelikosti s ≤ 4.
procedure poi s c ilist(list, koren);{ Drevo s korenom koren je 2-3 drevo. Nakljucno poiscemo list list.
Ce je prvotno drevo prazno, je list = 0. }begin
v := koren; list := 0;while v 6= 0 then begin
list := v ;if v .s > 0 then v := v .sin[nakljucno([1 : v .s])]else v := 0;
end;end.J.Kozak: PSA I, 2010-2011 45 / 57
procedure unija(korenA, korenB, koren);{ Drevesi s korenoma korenA in korenB sta neprazni 2-3 drevesi,
koren novi koren unije obeh 2-3 dreves. }poi s c ilist(vA, korenA);poi s c ilist(vB, korenB);while (vA.oce 6= 0) and (vB.oce 6= 0) then begin
vA := vA.oce; vB := vB.oce;end;if (vA.oce = 0) and (vB.oce = 0) then begin{ Drevesi s korenoma korenA in korenB sta enako globoki.
Generiramo nov koren in s tem poglobimo drevo. }novovozli s ce(koren);koren.s := 2;koren.max := max(vA.max , vB.max);koren.sin[1] := vA; koren.sin[2] := vB;vA.oce := koren; vB.oce := koren;
endelse
J.Kozak: PSA I, 2010-2011 46 / 57
if (vB.oce = 0) then begin{ Drevo s korenom korenB je plitvejse. }koren := korenA;
vA.oce.s := vA.oce.s + 1;
vA.oce.sin[vA.oce.s] := vB;
vB.oce := vA.oce;
vA.oce.max := max(vA.oce.max , vB.max);
{ Malo preurejena osnovna procedura preuredi . }preurediMax(vA.oce, koren);
endelse{ Drevo s korenom korenA je plitvejse. Zrcalni popravki. }
end.
J.Kozak: PSA I, 2010-2011 47 / 57
B-drevo
B-drevo je iskalno drevo, uravnotezeno po stopnji vozlisc in nivojulistov. Je razsiritev druzine 2-3 dreves. Ta podatkovna struktura jezelo pomembna povsod tam, kjer potrebujemo ucinkovit dostop dopodatkov na zunanjem pomnilniku, predvsem na obicajnih diskih.So osnova vecine baz podatkov. Vzemimo za primer relacijskobazo podatkov. Ta je mnozica tabel, povezanih z relacijami. Vtabeli lahko iscemo dolocen podatek najpogosteje le zaporedno. Cepotrebujemo odgovore hitreje ali ce hocemo tabele brez preurejanjapregledovati v razlicnih vrstnih redih, nad tabelami zgradimoB-drevesa, drevesa kljucev. B-dreves poznamo mnogo vrst.Razlikujejo se po tem, kje se hranijo dodatni podatki, ki pripadajoposameznim kljucem, kaksne omejitve stopnjam notranjih vozliscnalozimo ipd. Srecamo oznake B,B′,B+,B∗ itd. Tu si bomopogledali osnovna B-drevesa in poenostavili razmislek spredpostavko, da se vsi dodatni podatki, ki pripadajo posameznemkljucu, skrivajo za njim. Ko prestavimo kljuc, prestavimo hkratitudi podatke.
J.Kozak: PSA I, 2010-2011 48 / 57
Definicija B-drevesaB-drevo T = T (t) = T (t, koren) minimalne stopnje t ≥ 2 skorenom koren je urejeno iskalno drevo, ki ima tele lastnosti:
Vsako vozlisce v ima polja:n . . . stevilo kljucev v vozliscu,kljuc[1 : n] . . . tabela kljucev, urejenih nepadajoce,list . . . logicna vrednost, ki pove, ali je vozlisce list ali ne.
Vsako notranje vozlisce ima n + 1 kazalcev sin[1 : n + 1] napoddrevesa. Kazalci v listih niso definirani.Kljuci kljuc[1 : n] locijo kljuce v poddrevesih,
k1 ≤ kljuc[1] < k2 < · · · ≤ kljuc[n] < kn+1, ki ∈ T (t, sin[i ])
Vsi listi so na istem nivoju, globini B-drevesa.Vsako vozlisce, z izjemo korena, ima vsaj t − 1 kljucev. Cedrevo T ni prazno, ima koren vsaj en kljuc.Stopnja vozlisc je kvecjemu 2t. Vozlisce, ki ima 2t − 1kljucev, je polno vozlisce.
J.Kozak: PSA I, 2010-2011 49 / 57
IzrekNaj B-drevo T (t) vsebuje n ≥ 1 kljucev. Za globino h velja
h ≤ 1 + logtn + 1
2 .
Dokaz. Koren vsebuje je stopnje vsaj dve in vsebuje vsaj en kljuc.Druga vozlisca vsebujejo vsaj t − 1 kljucev in so, z izjemo listov,stopnje vsaj t. Torej je stevilo vozlisc vsaj
n ≥ 1 + (t − 1)(
2 + 2t + · · ·+ 2th−2)
= 1 + 2(t − 1)th−1 − 1
t − 1
inth−1 ≤ n + 1
2 .
Prav izbira minimalne stopnje da veliko uporabno mocB-drevesom. Poisci kljuc: O (t logt n).
J.Kozak: PSA I, 2010-2011 50 / 57
procedure poi s c i(koren, k);
{ Poisce v B-drevesu s korenom koren (v glavnem pomnilniku)kljuc k. Ce ga najde, je rezultat par (x , i).Tu je x vozlisce, kjer je bil kljuc najdenin i indeks, tak, da je x .kljuc[i ] = k. Ce kljuca ni, vrne (0, 0). }
beginx := koren;
i := 1;
while i ≤ x .n and k > x .kljuc[i ] do i := i + 1;
if i ≤ x .n and k = x .kljuc[i ] then return(x , i);
if x .list thenreturn(0, 0)
else beginberi z diska(x .sin[i ]);
return(x .sin[i ], k);
end;
end;J.Kozak: PSA I, 2010-2011 51 / 57
procedure pripravi(koren);
{ Pripravi prazno B-drevo s korenom koren. }begin
novovozli s ce(koren);
koren.list := true;
koren.n := 0;pi s i na disk(koren);
end;
J.Kozak: PSA I, 2010-2011 52 / 57
procedure razdelisina(x , i , y);
{ Razdeli polno vozlisce y v B-drevesu minimalne stopnje t v dvenovi vozlisci. Vozlisce y je pri klicu stopnje 2t, x njegov oce,ki ni poln (stopnja(x) < 2t). Indeks i , 1 ≤ i ≤ 2t − 1, pove,kateri sin vozlisca x je y , x .sin[i ] = y . Vozlisci x in y stapo privzetku v glavnem pomnilniku. }
begin{ Vozlisce z prevzame desni del y . }pripravi(z);
z .list := y .list;
z .n := t − 1;
for j := 1 to t − 1 do z .kljuc[j] := y .kljuc[j + t];
if not y .list thenfor j := 1 to t do z .sin[j] := y .sin[j + t];
y .n := t − 1;J.Kozak: PSA I, 2010-2011 53 / 57
{ Razmaknemo kljuce in kazalce v vozliscu x . }for j := x .n + 1 downto i + 1 do x .sin[j + 1] := x .sin[j];x .sin[i + 1] := z ;
for j := x .n downto i do x .kljuc[j + 1] := x .kljuc[j];x .kljuc[i ] := y .kljuc[t];
x .n := x .n + 1;
pi s i na disk(y);
pi s i na disk(z);
pi s i na disk(x);
end;
J.Kozak: PSA I, 2010-2011 54 / 57
procedure vstavi(koren, k);{ Vstavi kljuc k v B-drevo s korenom koren, ob predpostavki,
da kljuca k v drevesu se ni. }begin
r := koren;if r .n = 2t − 1 then begin{ Koren je poln. Razcepimo ga. }pripravi(s);koren := s;s.list := false;s.n := 0;s.sin[1] := r ;razdelisina(s, 1, r);vstavivnepolno(s, k);
endelse
vstavivnepolno(r , k);end;
J.Kozak: PSA I, 2010-2011 55 / 57
procedure vstavivnepolno(koren, k);
{ Vstavi kljuc k v B-drevo minimalne stopnje t s korenom koren.Za stopnjo korena mora veljati ≤ 2t − 1, torej koren ni poln.Za kljuc k predpostavljamo, da ga v drevesu se ni bilo. }
beginx := koren;
i := x .n;
if x .list then beginwhile i ≥ 1 and k < x .kljuc[i ] do begin
x .kljuc[i + 1] := x .kljuc[i ];i := i − 1;
end;x .kljuc[i + 1] := k;x .n := x .n + 1;pi s i na disk(x);
endJ.Kozak: PSA I, 2010-2011 56 / 57
else beginwhile i ≥ 1 and k < x .kljuc[i ] do i := i − 1;
i := i + 1;
beri z diska(x .sin[i ]);
if x .sin[i ].n = 2t − 1 then beginrazdelisina(x , i , x .sin[i ]);
if k > x .kljuc[i ] then i := i + 1;
end;
vstavinepolno(x .sin[i ], k);
end;
end;
J.Kozak: PSA I, 2010-2011 57 / 57