Föreläsning 6
Sökträd: AVL-träd,
”Multi-Way”-sökträd, B-träd
TDDC70/91: DALG
Utskriftsversion av föreläsning i Datastrukturer och algoritmer 23 september 2013
Tommy Färnqvist, IDA, Linköpings universitet
6.1
Innehåll
Introduktion
find,insert och remove i ett binärt sökträd tar O(h) tid, där h är höjden av trädet.
Håll sökträdet balanserat!!
6.2
Innehåll
1
AVL-träd
1
2 (2, 3)-träd
13
3
15
1
B-träd
6.3
AVL-träd
AVL-träd
•
•
•
•
Självbalanserande BST/höjdbalanserat BST
AVL = Adelson-Velskii och Landis, 1962
Idén: Håll reda på balansinformation i varje nod
AVL-egenskapenFör varje intern nod v i T skiljer sig höjden av barnen till v med högst 1 . . . eller
alternativt. . . För varje intern nod v i T gäller att b(v) ∈ {−1, 0, 1}, där
b(v) = height(leftChild(v)) − height(rightChild(v))
6.4
Maximal höjd av AVL-träd
Proposition 1 (10.2 i kursboken). Höjden av ett AVL-träd som lagrar n poster är O(log n).
Vilket får som följd att. . .
Proposition 2. Vi kan göra find, insert och remove i ett AVL-träd i tid O(log n) medan vi bevarar AVLegenskapen.
6.5
1
Exempel: ett AVL-träd
6.6
44
17
3
1
78 2
0
0
1
32
50
88
0
48
0
62
Insättning i ett AVL-träd
• Den nya noden gör att trädhöjden förändras och att trädet måste höjdbalanseras.
– Man kan hålla reda på delträdens höjd på olika sätt:
∗ Lagra höjden explicit i varje nod
∗ Lagra balansfaktorn för noden
• Förändringen brukar beskrivas som en höger- eller vänsterrotation av ett delträd.
• Det räcker med en rotation för att få trädet i balans igen.
6.7
Insättning i AVL-träd (enkla fall)
6.8
Insättningsalgoritm
• Starta från den nya noden och leta uppåt tills man hittar en nod x s.a. dess ”grandparent” z är obalanserad. Markera x:s förälder med y.
• Gör en rekonstruering av trädet så här:
– Döp om x, y, z till a, b, c baserat på deras inorder-ordning.
– Låt T0 , T1 , T2 , T3 vara en uppräkning i inorder av delträden till x, y och z. (Inget av delträden får
ha x, y eller z som rot.)
– z byts mot b, dess barn är nu a och c.
– T0 och T1 är barn till a och T2 och T3 är barn till c.
6.9
2
Exempel: insättning i ett AVL-träd
6.10
44
4
z/c
17
1
78 3
y/a
0
32
0
2
T3 88
50
x/b
0
1
48
T0
62
T1 54
Exempel: insättning i ett AVL-träd
44
T0
17
6.11
b
3
1
a
T1
c
T2
T3
62 2
0
1
1
32
78
50
0
0
0
54
48
88
Fyra olika rotationer
b=y
a=z
enkel rotation
b=y
a=z
c=x
c=x
T3
T0
T1
T3
T0
T1
T2
T2
Om b = y kallas det en enkel rotation.”Rotera upp y över z”
6.12
Fyra olika rotationer
b=y
c=z
enkel rotation
a=x
b=y
c=z
a=x
T0
T2
T0
T3
T1
T2
T3
T1
Om b = y kallas det en enkel rotation.”Rotera upp y över z”
3
6.13
Fyra olika rotationer
b=x
a=z
dubbel rotation
c=y
a=z
c=y
b=x
T2
T0
T2
T3
T0
T1
T3
T1
Om b = x kallas det en dubbel rotation.”Rotera upp x över y och sedan över z”
6.14
Fyra olika rotationer
b=x
c=z
dubbel rotation
a=y
a=y
c=z
b=x
T0
T3
T1
T1
T0
T2
T3
T2
Om b = x kallas det en dubbel rotation.”Rotera upp x över y och sedan över z”
6.15
Ett annat sätt att beskriva det på
y
x
T2
T0
T1
Antag att vi har balans. . .
6.16
Ett annat sätt att beskriva det på
4
y
x
T2
T1
T0
. . . och sedan stoppar in något som sabbar den
6.17
Ett annat sätt att beskriva det på
y
x
T2
T1
T0
Gör en enkel rotation
6.18
Ett annat sätt att beskriva det på
y
x
T2
T1
T0
5
Gör en enkel rotation
6.19
Ett annat sätt att beskriva det på
y
x
T2
T1
T0
Gör en enkel rotation
6.20
Ett annat sätt att beskriva det på
x
y
T1
T20
T0
Gör en enkel rotation
6.21
Ett annat sätt att beskriva det på
6
x
y
T0
T1
T20
Gör en enkel rotation
6.22
Ett annat sätt att beskriva det på
x
y
T0
T1
T20
Klart!
6.23
Ett annat sätt att beskriva det på
z
y
7
Ett nytt exempel. . .
6.24
Ett annat sätt att beskriva det på
z
y
. . . den här gången stoppar vi in något på ett annat ställe
6.25
Ett annat sätt att beskriva det på
z
y
Prova en enkel rotation igen. . .
6.26
Ett annat sätt att beskriva det på
8
y
z
. . . hmm, vi har inte fått balans
6.27
Ett annat sätt att beskriva det på
z
y
Börja om från början. . . och titta på strukturen i y
Ett annat sätt att beskriva det på
z
y
T3
x
T0
T1
T2
9
6.28
Vi får lov att göra en dubbel rotation
6.29
Ett annat sätt att beskriva det på
z
y
T3
x
T0
T1
T2
Vi får lov att göra en dubbel rotation
6.30
Ett annat sätt att beskriva det på
z
y
T3
x
T0
T1
T2
Vi får lov att göra en dubbel rotation
6.31
Ett annat sätt att beskriva det på
10
z
y
T3
x
T0
T1
T2
Vi får lov att göra en dubbel rotation
6.32
Ett annat sätt att beskriva det på
z
y
T3
x
T0
T1
T2
Vi får lov att göra en dubbel rotation
6.33
Ett annat sätt att beskriva det på
x
y
T0
z
T1
T2
T3
11
Vi får lov att göra en dubbel rotation
6.34
Ett annat sätt att beskriva det på
x
y
T0
z
T1
T2
T3
Klart!
6.35
Trenodsrekonstruering = rotationer. . .
Vissa författare använder vänster- och högerrotationer: Enkel vänsterrotation:
• vänstra delen av delträdet (a och j) sänks ner
• vi har ”roterat (upp) b över a”
a
b
b
j
a
c
k
l
m
j
c
k
m
l
6.36
Dubbla rotationer. . .
Två rotationer behövs när noderna som ska balanseras om är placerade i ett sicksackmönster.
• Rotera upp b över a
• Rotera upp b över c
c
a
k
b
a
a
b
j
c
b
m
j
k
l
l
m
j
c
k
l
m
6.37
12
Borttagning i ett AVL-träd
• find och remove som i ett vanligt binärt sökträd
• Uppdatera balansinformationen på väg tillbaka upp till roten
• Om för obalanserat: Strukturera om . . . men. . .
– När vi återställer balansen på ett ställe kan det uppstå obalans på ett annat
– Måste upprepa balanseringen (eller kontroll av balansen) till dess vi når roten
– Högst O(log n) ombalanseringar
6.38
2 (2, 3)-träd
Ny approach: släpp på något av kraven
• AVL-träd: binärt träd, accepterar viss (liten) obalans. . .
• Kom ihåg: Fullt binärt träd: icke-tomt; graden är antingen 0 eller 2 för varje nod Perfekt binärt träd:
fullt, alla löv har samma djup
• Kan vi bygga och underhålla ett perfekt träd (om vi struntar i ”binärt”)? Då skulle vi alltid känna till
söktiden i värsta fall exakt!
6.39
(2, 3)-träd
Förut:
• Ett ”pivotelement”
• Om större letar vi till höger
• Om mindre letar vi till vänster
Nu:
• Tillåt flera (nämligen 1–2) ”pivotelement”
• Antalet barn till en intern nod är antalet pivotelement + 1 (dvs 2–3)
5
2
8
5 10
2
8
12
6.40
Mer generellt (a, b)-träd
• Varje nod är antingen ett löv eller så har den c barn, där a ≤ c ≤ b Varje nod har mellan a − 1 och
b − 1 pivotelement
• 2 ≤ a ≤ (b + 1)/2 (men roten behöver bara ha minst två barn (eller inga) även när a > 2 gäller)
• find fungerar ungefär som förut
• insert måste kolla att noden inte blivit överfull (i så fall måste noden delas upp)
• remove kan leda till att man måste slå ihop noder eller föra över värden mellan noder
Proposition 3 (14.1 i kursboken). Höjden av ett (a, b)-träd som lagrar n dataelement är Ω(log n/ log b) och
O(log n/ log a).
⇒ Plattare träd, men mer jobb i noderna.
6.41
13
Insättning i ett (a, b)-träd med a = 2 och b = 3
5
Insert(10)
5 10
Insert(15)
10
5
Insert(18)
15
• Så länge det finns plats i barnet vi hittar, lägg till elementet i det barnet. . .
• Om fullt, dela upp och tryck det utvalda pivotelementet uppåt. . . . . . detta kan hända upprepade gånger
10
5
10
Insert(17)
15 18
5
10 17
15 17 18
5
15
18
6.42
Borttagning i (2, 3)-träd
Tre fall:
• Inga villkor bryts genom borttagning
• Ett löv tas bort (blir tomt) För då över någon annan nyckel till det lövet, . . . ok om vi har syskon med
2+ element
20
?
10 17
5
15
Överföring
av 30 och 35
30
Delete(25)
30
18
25
10 17
?
35 40
20
35 40
30
5
35 40
15
35
18
30
40
6.43
Borttagning i (2, 3)-träd
• Om ett löv tas bort (blir tomt)
• För då över någon annan nyckel till det lövet, eller
• Slå ihop det med en granne
10 17
20
Delete(18)
10 17
5
15
5
35
18
30
15
?
20
10
10
40
5
15
17
5
35
15 17
30
40
6.44
14
Borttagning i (2, 3)-träd
• En intern nod blir tom Roten: ersätt med föregångare eller efterföljare i inorder Reparera sedan inkonsistenser med lämpliga ihopslagningar och överföringar. . .
Ersätt...
...slå ihop löv
Delete(20)
?
20
10 5
3
17
För få element internt...
...slå ihop noder
10 35
30
40
5
17
?
? 35
17
30
40
35
5 10
30
17 35
40
5 10 30
40
6.45
B-träd
B-träd
•
•
•
•
Används för att upprätthålla ett index över externt data (t.ex. innehållet på ett skivminne)
Är ett (a, b)-träd där a = db/2e, dvs b = 2a − 1
Vi kan nu välja b så att en full nod precis tar upp ett block på skivminnet
Genom att välja a = db/2e kommer vi alltid att fylla ett helt block på skivminnet när två block slås
samman!
• B-träd (och varianter) används i många filsystem och databaser
– Windows: HPFS
– Mac: HFS, HFS+
– Linux: ReiserFS, XFS, Ext3FS, JFS
– Databaser: ORACLE, DB2, INGRES, PostgreSQL
6.46
15