Algoritmai ir duomenų struktūros ( AD S)
description
Transcript of Algoritmai ir duomenų struktūros ( AD S)
Problema
Dvejetainis paieškos medis (DPM) gali „išsigimti“ (išsibalansuoti), tada paieška jame tampa neefektyvi – blogiausiu atveju ji gali tapti ... (geriausiu atveju paieškos DPM sudėtingumas yra ...).
Problemos sprendimo būdai:1)laikas nuo laiko medį subalansuoti (balansavimas „brangi“ operacija);2)naudoti specialius (neišsibalansuojančius) medžius (pvz., AVL medžius).
AVL medis
Apibrėžimas: AVL medis – tai (besibalansuojantis) dvejetainis paieškos medis, kurio (1) šaknies dešiniojo ir kairiojo pomedžių aukščiai skiriasi daugiausiai vienetu ir (2) abu pomedžiai, savo ruožtu, tai pat yra AVL medžiai.
AVL medis buvo pirmas besibalansuojantis medis. Jis buvo pasiūlytas 1962 m. ir gavo vardą iš savo kūrėjų (G. M. Adelson-Velsky ir E. M. Landis).
Ar efektyvi paieška AVL medyje?
AVL medžiai
― /
―
―
\
― /
―― ―
―
― \
― ― ―
―
―
― ―
/
― /
Ne AVL medžiai
―
//
/
―
\
\\
― \\
―
/
―
\
―
// \\
――
\\
―
Paprastas elementų įterpimas
― \
―
―
― ―
―
\
― \
――
\
― ―
― ――
―
/ ―
― ―
―
/
\
/ /
―
―
/
―
/
\
/ ―
――
―
/
―
/
\
― ―
30
30
20 50
60
50
60
30
45
20
10
40
10
20
30
50
45 60
40 55
20 50
10 45 6025
40 55
30
20 50
10 45 60
30
20 50
30
20
30
50
45 60
30
50
AVL medžio elementų tipas
type Balance_Factor_Type = (LH, EH, RH);{ LH : left higher; EH : equal heights; RH : right higher }
type AVL_Tree_Type = ^AVL_Tree_Node_Type;
type AVL_Tree_Node_Type = record left, right : AVL_Tree_Type; bf : Balance_Factor_Type; info : ... end.
Įterpimas
procedure Insert(var root : AVL_Tree_Type; newnode : AVL_Tree_Type; var taller : Boolean);var tallersubtree: Boolean;begin if root = nil then begin root := newnode; root^.left := nil; root^.right := nil; root^.bf := EH; taller := true; end else with root^ do if newnode^.info.key = info.key then Error else ...
Įterpimas (2)
else if newnode^.info.key < info.key then begin Insert(left, newnode, tallersubtree); if tallersubtree then case bf of LH: LeftBalance; EH: begin bf := LH; taller := true end; RH: begin bf := EH; taller := false end; end else taller := false end else ...
Įterpimas (3)
else begin Insert(right, newnode, tallersubtree); if tallersubtree then case bf of LH: begin bf := EH; taller := false end; EH: begin bf := RH; taller := true
end; RH: RightBalance; end else taller := false endend;
Balanso atstatymas sukimu į kairę
Pasukimasį kairę\\
\
1T
2T3T
―
―
1T 2T3T
50
30 50
30
h+1h
h h h
h+1
Bendras aukštis = h+3 Bendras aukštis = h+2
Sukimo į kairę procedūra
procedure RotateLeft(var p: AVL_Tree_Type); {p – šaknis, kurios pomedis yra sukamas}var temp: pointer;begin if p = nil then Error else if p^.right = nil then Error else begin temp := p^.right; p^.right := temp^.left; temp^.left := p; p := temp; end;end;
Balanso atstatymas dvigubu pasukimu
\\
/ 50
45
30
1T
4T
―
1T 2T
45
30 50
3T4T
Tampa
2T 3T
h-1 arba
hh h
h
h
h-1 arba
hVieno iš T1 ar T2 aukštis yra h
Bendras aukštis = h+3 Bendras aukštis = h+2
Dešinio balansavimo procedūra
procedure RightBalance;var x, {šaknies dešinysis pomedis} w: AVL_Tree_Type; {kairysis x^ pomedis}begin x := root^.right; case x^.bf of RH: begin root^.bf := EH; x^.bf := EH; RotateLeft(root); taller := false end; EH: Error;
Dešinio balansavimo procedūra (2)
LH: begin w := x^.left; case w^.bf of EH: begin root^.bf := EH; x^.bf := EH end; LH: begin root^.bf := EH; x^.bf := RH end; RH: begin root^.bf := LH; x^.bf := EH end; end;
Dešinio balansavimo procedūra (3)
w^.bf := EH; RotateRight(x); root^.right := x; RotateLeft(root); taller := false;
end endend;
Procedūros RotateRight ir LeftBalance yra labai panašios į RotateLeft ir RightBalance atitinkamai.
Algoritmo veikimo demonstravimas
\
― 40
20
―
\\
\ 40
60
―
― ―20 60
20 40
――
\
― ―20 60
50 70
40
―
―
/
\\
― /20 60
50 70
45
―― ―
―
― \40 60
20 7045
40 50
Apibendrinimas
Didžiausias AVL medžių privalumas, kad jų aukštis visada labai artimas teoriniam minimumui
)1(log 2 n
Pabandykime rasti blogiausią atvejį: koks gali būti maksimalus AVL medžio, turinčio n viršūnių, aukštis?
Ieškosime AVL medžio, kurio aukštis h, minimalaus viršūnių skaičiaus.
AVL medžio viršūnių skaičius
Fh yra nagrinėjamas AVL medis, kurio aukštis h. Fk ir Fd yra jo kairysis ir dešinysis pomedžiai. Vieno iš šių pomedžių, tarkime Fk, aukštis bus (h - 1), o kito (Fd) – (h - 1) arba (h - 2). Kadangi medis Fh turi mažiausią skaičių viršūnių, tai Fd aukštis turi būti (h - 2). Iš čia gauname, kad:
|Fh| = |Fh - 1| + |Fh - 2| + 1
Čia |Fh| yra medžio, kurio aukštis h, viršūnių skaičius.
Tokie AVL medžiai dar yra vadinami Fibonačio medžiais
Fibonačio medžių pavyzdžiai
AVL medžio maksimalus aukštis
Prie gautosios lygybės pridėję po 1, gauname:|Fh| + 1 = (|Fh - 1| + 1) + (|Fh - 2| + 1)
|Fh| + 1 yra Fibonačio sekos narys, todėl :
|Fh| + 1 ≈
Išreiškus iš šios lygybės h ≈ 1,44 log |Fh|. Tai reiškia, kad pačiu blogiausiu atveju AVL medžio su n viršūnių apytikslis aukštis yra 1,44 log n.
3
2
51
5
1
h
Tikėtinas DPM aukštis
Vidutinis palyginimo operacijų skaičius vidutiniame DPM su n viršūnių apytiksliai lygus:
Vidutiniam DPM apytiksliai reikia karto 1,39 karto daugiau palyginimo operacijų negu visiškai subalansuotam medžiui.
))(lg2ln2(ln2 nn
Klausimai
?