Självbalanserande träd AVL-träd Koffman & Wolfgang kapitel 9, avsnitt 1 2 1
Balanserade träd Nodbalanserat träd: skillnaden i antalet noder mellan vänster och höger delträd är högst 1 Höjdbalanserat träd: skillnaden i höjd (djup) mellan vänster och höger delträd är högst 1 Nivåbalanserat träd: alla nivåer är fyllda, utom den nedersta som fylls på från vänster till höger Notera att höjden av alla dessa träd är logaritmisk: h = O(log n), där n är antalet noder i trädet 2
Självbalanserande sökträd Effektiviteten hos ett binärt sökträd är proportionell mot höjden på trädet: ett balanserat träd är effektivare än ett obalanserat i värsta fall kan sökträdet ha linjär höjd, dvs h = O(n) då blir komplexiteten också linjär För att lösa detta problem introducerar vi självbalanserande träd: vid insättning och uttagning så balanserar trädet om sig om det är nödvändigt 3
Obalanserade träd Sökningar i detta obalanserade träd är O(n), inte O(log n) Här är ett mer realistiskt exempel på ett obalanserat träd 4
Rotering Vi behöver en operation på binära träd som ändrar de relativa höjderna mellan vänster och höger delträd, men bibehåller sökträdsegenskapen 5
Rotering, exempel root = left right = data = 1 = left right = data = 2 null = left right = null data = 4 null = left right = data = 5 null = left right = null data = 15 null = left right = null data = 7 6
Rotering, exempel root = left right = data = 1 = left right = data = 2 null = left right = null data = 4 null = left right = data = 5 null = left right = null data = 15 1. Remember value of root.left null = left right = null data = 7 7
Rotering, exempel root temp = left right = data = 1 = left right = data = 2 null = left right = null data = 4 null = left right = data = 5 null = left right = null data = 15 1. Remember value of root.left null = left right = null data = 7 7
Rotering, exempel root temp = left right = data = 2 = left right = data = 1 null = left right = null data = 4 null = left right = data = 5 null = left right = null data = 15 1. Remember value of root.left 2. Set root.left to value of temp.right null = left right = null data = 7 8
Rotering, exempel root temp = left right = data = 2 = left right = data = 1 null = left right = null data = 4 null = left right = data = 5 null = left right = null data = 15 1. Remember value of root.left 2. Set root.left to value of temp.right null = left right = null data = 7 8
Rotering, exempel root temp = left right = data = 2 = left right = data = 1 null = left right = null data = 4 null = left right = data = 5 null = left right = null data = 7 null = left right = null data = 15 1. Remember value of root.left 2. Set root.left to value of temp.right 3. Set temp.right to root 9
Rotering, exempel root temp = left right = data = 2 = left right = data = 1 null = left right = null data = 4 null = left right = data = 5 null = left right = null data = 7 null = left right = null data = 15 1. Remember value of root.left 2. Set root.left to value of temp.right 3. Set temp.right to root 9
Rotering, exempel root temp = left right = data = 2 = left right = data = 1 null = left right = null data = 4 null = left right = data = 5 null = left right = null data = 7 null = left right = null data = 15 1. Remember value of root.left 2. Set root.left to value of temp.right 3. Set temp.right to root 4. Set root to temp 1
Rotering, exempel root temp = left right = data = 2 = left right = data = 1 null = left right = null data = 4 null = left right = data = 5 null = left right = null data = 7 null = left right = null data = 15 1. Remember value of root.left 2. Set root.left to value of temp.right 3. Set temp.right to root 4. Set root to temp 1
11 Rotering, exempel
Rotering, exempel root null = left right = data = 5 = left right = data = 1 = left right = data = 2 null = left right = null data = 7 null = left right = null data = 15 null = left right = null data = 4 11
12 class BinarySearchTreeWithRotate
AVL-träd AVL står för Adelson-Velskii (Адельсóн-Вéльский) och Landis (Лáндис) som kom på trädalgoritmerna AVL-trädet håller reda på vänster-höger-balansen i varje delträd: när element läggs till eller tas bort från trädet, uppdateras balansen för alla delträd från insättningspunkten upp till roten om balansen hamnar utanför 1 till +1, roteras trädet för att få det i balans igen 13
Balansera ett vänster-vänsterträd 5 25 c a b 14
Balansera ett vänster-vänsterträd 5 25 c a b varje rosa triangel representerar ett träd med höjd k 14
Balansera ett vänster-vänsterträd 5 25 c a b den lila trapezoiden representerar en insättning, som ger detta träd höjden k+1 15
Balansera ett vänster-vänsterträd 5 25 c a b formeln h R h L används för att beräkna balansen 16
Balansera ett vänster-vänsterträd 5 k (k + 1) 25 c a b formeln h R h L används för att beräkna balansen 16
Balansera ett vänster-vänsterträd 5 k (k + 1) 25 1 c a b formeln h R h L används för att beräkna balansen 16
Balansera ett vänster-vänsterträd 5 k (k + 2) k (k + 1) 25 1 c a b formeln h R h L används för att beräkna balansen 16
Balansera ett vänster-vänsterträd 5 2 k (k + 2) k (k + 1) 25 1 c a b formeln h R h L används för att beräkna balansen 16
Balansera ett vänster-vänsterträd vänster och höger delträds höjd är ointressant; endast skilladen betyder något 5 2 k (k + 2) k (k + 1) 25 1 c a b formeln h R h L används för att beräkna balansen 16
Balansera ett vänster-vänsterträd 25 1 5 2 när både roten och vänster delträd lutar åt vänster, så kallas trädet ett vänster-vänsterträd c a b 17
Balansera ett vänster-vänsterträd 25 1 5 2 vänster-vänsterträd kan balanseras genom att rotera åt höger c a b 18
Balansera ett vänster-vänsterträd 25 5 a b c 19
Balansera ett vänster-vänsterträd 25 5 a b c notera att den totala höjden inte har ändrats jämfört med innan insättningen! 19
Balansera ett vänster-högerträd 5 25 c a b 2
Balansera ett vänster-högerträd 5 (k + 1) - k 25 +1 c a b 2
Balansera ett vänster-högerträd k - (k + 2) 5-2 (k + 1) - k 25 +1 c a b 2
Balansera ett vänster-högerträd 5-2 25 +1 c a b ett vänster-högerträd kan inte balanseras med en enkel högerrotation 21
Balansera ett vänster-högerträd 5-2 25 +1 c a b delträd b behöver expanderas i sina egna delträd bl och br 22
Balansera ett vänster-högerträd 5-2 25 +1 4-1 c a b L b R 4 är vänster-tungt: vänster delträd kan nu roteras åt vänster 23
Balansera ett vänster-högerträd 5-2 4-2 25 c b R b L a 24
Balansera ett vänster-högerträd 5-2 4-2 25 c b R a b L nu är det övergripande trädet vänster-vänster, så vi kan rotera åt höger för att balansera det 24
Balansera ett vänster-högerträd 4 25 5 +1 b L b R a c 25
Balansera ett vänster-högerträd 5-2 25 +1 4 +1 c a b L b R antag nu att elementet stoppades in i br istället för bl 26
Balansera ett vänster-högerträd 5-2 25 +1 4 +1 c a b L b R 1. rotera vänster delträd åt vänster 27
Balansera ett vänster-högerträd 5-2 4-1 25-1 b R c b L a 28
Balansera ett vänster-högerträd 5-2 2. rotera trädet åt höger 4-1 25-1 b R c b L a 28
Balansera ett vänster-högerträd 4 25-1 5 b L b R a c 29
Fyra sorters obalanserade träd Vänster-vänster (föräldern < 1, vänster barn ) rotera åt höger runt föräldern Vänster-höger (föräldern < 1, vänster barn > ) rotera åt vänster runt barnet rotera åt höger runt föräldern Höger-höger (föräldern > 1, höger barn ) rotera åt vänster runt föräldern Höger-vänster (föräldern > 1, höger barn < ) rotera åt höger runt barnet rotera åt vänster runt föräldern 3
Balansering av de fyra olika fallen (bilden är från Wikipedia) 31
Ett större AVL-exempel Nu ska vi bygga ett AVL-träd för orden i The quick brown fox jumps over the lazy dog 32
The quick brown The +2 quick -1 brown The overall tree is right-heavy (Right-Left) parent balance = +2 right child balance = -1 33
The quick brown The +2 quick -1 brown 1. Rotate right around the child 34
The quick brown The +2 brown +1 quick 1. Rotate right around the child 35
The quick brown The +2 brown +1 quick 1. Rotate right around the child 2. Rotate left around the parent 36
The quick brown brown The quick 1. Rotate right around the child 2. Rotate left around the parent 37
The quick brown fox brown The quick Insert fox 38
The quick brown fox brown +1 The quick -1 Insert fox fox 39
The quick brown fox jumps brown +1 The quick -1 Insert jumps fox 4
The quick brown fox jumps brown +2 The quick -2 Insert jumps fox +1 jumps 41
The quick brown fox jumps brown +2 The quick -2 fox +1 jumps The tree is now left-heavy about quick (Left-Right case) 42
The quick brown fox jumps brown +2 The quick -2 fox +1 jumps 1. Rotate left around the child 43
The quick brown fox jumps brown +2 The quick -2 jumps -1 fox 1. Rotate left around the child 44
The quick brown fox jumps brown +2 The quick -2 jumps -1 fox 1. Rotate left around the child 2. Rotate right around the parent 45
The quick brown fox jumps brown +1 The jumps fox quick 1. Rotate left around the child 2. Rotate right around the parent 46
The quick brown fox jumps over brown +1 The jumps Insert over fox quick 47
The quick brown fox jumps over brown +2 The jumps +1 Insert over fox quick -1 over 48
The quick brown fox jumps over brown +2 The jumps +1 fox quick -1 over We now have a Right-Right imbalance 49
The quick brown fox jumps over brown +2 The jumps +1 fox quick -1 over 1. Rotate left around the parent 5
The quick brown fox jumps over jumps brown quick -1 The fox over 1. Rotate left around the parent 51
The quick brown fox jumps over the jumps brown quick -1 Insert the The fox over 52
The quick brown fox jumps over the jumps brown quick Insert the The fox over the 53
quick brown fox jumps over the lazy jumps brown quick Insert lazy The fox over the 54
quick brown fox jumps over the lazy jumps +1 brown quick -1 Insert lazy The fox over -1 the lazy 55
ick brown fox jumps over the lazy dog jumps +1 brown quick -1 Insert dog The fox over -1 the lazy 56
ick brown fox jumps over the lazy dog! jumps brown +1 quick -1 Insert dog The fox -1 over -1 the dog lazy 57
58 Att implementera ett AVL-träd
Insättning i ett AVL-träd Enklaste sättet att hålla trädet balanserat är att aldrig låta det bli obalanserat om någon nod blir kritiskt obalanserad, balansera om den direkt identifiera kritiska noder genom att kontrollera nodbalansen när du returnerar efter att ha lagt in det nya elementet 59
Insättning i ett AVL-träd Algoritm för insättning i ett AVL-träd 1. if the root is null: 2. Create a new tree with the item at the root and return true 3. else if the item is equal to root.data: 4. The item is already in the tree; return false 5. else if the item is less than root.data: 6. Recursively insert the item in the left subtree 7. if the height of the left subtree has increased (increase is true): 8. Decrement balance 9. if balance is zero, reset increase to false 1. if balance is less than 1: 11. Reset increase to false 12. Perform a rebalanceleft 13. else if the item is greater than root.data: 14. The processing is symmetric to Steps 4 through 1. 15. Note that balance is incremented if increase is true, not decremented 6
rebalanceleft: första försöket Initial algoritm för rebalanceleft 1. if the left subtree has positive balance (Left-Right case): 2. Rotate left around left subtree root 3. Rotate right Denna algoritm är inte fullständig, eftersom nodbalanserna inte justerades. för ett vänster-vänsterträd så blir den slutliga balansen på rotnoden och dess högra barn vänster-högerträd är mer komplicerade 61
Rotationseffekter på balansen Om den obalanserade situation uppstod på grund av att elementet stoppades in i: delträd bl (vänster-höger-vänster): roten och rotens vänstra barn har balansen och balansen till vänstra barnet är +1 62
Rotationseffekter på balansen Om den obalanserade situation uppstod på grund av att elementet stoppades in i: delträd br (vänster-höger-höger): roten och rotens högra barn har balansen och balansen till vänstra barnet är 1 63
rebalanceleft: reviderad version Revised Algorithm for rebalanceleft 1. if the left subtree has a positive balance (Left-Right case): 2. if the left-left subtree has a negative balance (Left-Right-Left case): 3. Set the left subtree (new left subtree) balance to 4. Set the left-left subtree (new root) balance to 5. Set the local root (new right subtree) balance to +1 6. else (Left-Right-Right case): 7. Set the left subtree (new left subtree) balance to 1 8. Set the left-left subtree (new root) balance to 9. Set the local root (new right subtree) balance to 1. Rotate the left subtree left 11. else (Left-Left case): 12. Set the left subtree balance to 13. Set the local root balance to 14. Rotate the local root right 64
decrementbalance När vi returnerar från en insättning i vänster delträd, behöver vi minska balansen Vi behöver också kunna berätta för föräldrarna ifall delträdets höjd har ökat eller ej 65 Det finns två fall: noden är balanserad: insättning i vänstra delträdet kommer att göra noden vänster-tung, och höjden kommer att öka med 1 noden är höger-tung: insättning i vänstra delträdet kommer att göra noden balanserad, och höjden kommer inte att öka
Borttagning från ett AVL-träd Borttagning av noder är ungefär som insättning fast precis tvärtom Metoderna decrementbalance, incrementbalance, rebalanceleft och rebalanceright behöver modifieras så att de sätter variabeln decrease förutom variabeln increase 66
Effektivitet hos AVL-träd AVL-träd är logaritmiska, O(log n), eftersom varje delträd är balanserat varje delträd får vara lite obalanserat (±1 balans), så trädet kan innehålla några hål i värsta fall (vilket är ovanligt) kan ett AVL-träd vara 1,44 gånger så högt som ett perfekt nodbalanserat träd empiriska tester visar att det i medeltal krävs,25+log(n) jämförelser för att sätta in element n eftersom vi kan ignorera konstanter så får vi en komplexitet på O(log n), även i praktiken 67