Upload
others
View
0
Download
0
Embed Size (px)
Citation preview
CSE 332: Data Structures & Parallelism
Lecture 8: AVL Trees
Ruth Anderson
Autumn 2019
Today
• Dictionaries
– AVL Trees
10/11/2019 2
10/11/2019
The AVL Balance Condition:
Left and right subtrees of every nodehave heights differing by at most 1
Define: balance(x) = height(x.left) – height(x.right)
AVL property: –1 balance(x) 1, for every node x
• Ensures small depth– Will prove this by showing that an AVL tree of height
h must have a lot of (*roughly* 2h) nodes
• Easy to maintain– Using single and double rotations
Note: height of a null tree is -1, height of tree with a single node is 0
3
10/11/2019 4
The AVL Tree Data Structure
4
131062
115
8
14127 9
Structural properties
1. Binary tree property
(0,1, or 2 children)
2. Heights of left and right
subtrees of every node
differ by at most 1
Result:
Worst case depth of any node
is: O(log n)
Ordering property
– Same as for BST15
111
84
6
10 12
7
Ex1: An AVL tree?
10/11/2019 5
3
1171
84
6
2
5
Ex2: An AVL tree?
10/11/2019 7
7
1161
82
5
3
Ex3: An AVL tree?
10/11/2019 9
4
Height of an AVL Tree?
Using the AVL balance property, we can
determine the minimum number of nodes in an
AVL tree of height h
Let S(h)be the minimum # of nodes in an AVL tree
of height h, then:
S(h) = S(h-1) + S(h-2) + 1
where S(-1) = 0 and S(0) = 1
Solution of Recurrence: S(h) 1.62h
10/11/2019 11
Let S(h)be the minimum # of nodes in an AVL tree of
height h, then:
S(h) = S(h-1) + S(h-2) + 1
where S(-1)=0 and S(0)=1
h Min height Tree S(h)
10/11/2019 12
Minimal AVL Tree (height = 0)
10/11/2019 13
Minimal AVL Tree (height = 1)
10/11/2019 14
Minimal AVL Tree (height = 2)
10/11/2019 15
Minimal AVL Tree (height = 3)
10/11/2019 16
Minimal AVL Tree (height = 4)
10/11/2019 17
The shallowness bound
Let S(h) = the minimum number of nodes in an AVL tree of height h
– If we can prove that S(h) grows exponentially in h, then a tree with n nodes has a logarithmic height
• Step 1: Define S(h) inductively using AVL property
– S(-1)=0, S(0)=1, S(1)=2
– For h 1, S(h) = 1+S(h-1)+S(h-2)
• Step 2: Show this recurrence grows really fast
– Similar to Fibonacci numbers
– Can prove for all h, S(h) > h – 1 where
is the golden ratio, (1+5)/2, about 1.62
– Growing faster than 1.6h is “plenty exponential”
h-1h-2
h
10/11/2019 18
Before we prove it
• Good intuition from plots comparing:
– S(h) computed directly from the definition
– ((1+5)/2) h
• S(h) is always bigger, up to trees with huge numbers of nodes
– Graphs aren’t proofs, so let’s prove it
10/11/2019 19
The Golden Ratio
62.12
51
This is a special number
• Aside: Since the Renaissance, many artists and architects have
proportioned their work (e.g., length:height) to approximate the golden ratio: If (a+b)/a = a/b, then a = b
• We will need one special arithmetic fact about :
2 = ((1+51/2)/2)2
= (1 + 2*51/2 + 5)/4
= (6 + 2*51/2)/4
= (3 + 51/2)/2
= 1 + (1 + 51/2)/2
= 1 +
10/11/2019 20
The proof
Theorem: For all h 0, S(h) > h – 1
Proof: By induction on h
Base cases:
S(0) = 1 > 0 – 1 = 0 S(1) = 2 > 1 – 1 0.62
Inductive case (k > 1):
Show S(k+1) > k+1 – 1 assuming S(k) > k – 1 and S(k-1) > k-1 – 1
S(k+1) = 1 + S(k) + S(k-1) by definition of S
> 1 + k – 1 + k-1 – 1 by induction
= k + k-1 – 1 by arithmetic (1-1=0)
= k-1 ( + 1) – 1 by arithmetic (factor k-1 )
= k-1 2 – 1 by special property of
= k+1 – 1 by arithmetic (add exponents)
S(-1)=0, S(0)=1, S(1)=2For h 1, S(h) = 1+S(h-1)+S(h-2)
10/11/2019 21
Good news
Proof means that if we have an AVL tree, then find is O(log n)
But as we insert and delete elements, we need to:
1. Track balance
2. Detect imbalance
3. Restore balance
10/11/2019 22
92
5
10
7
Is this tree AVL balanced?How about after insert(30)?
15
20
An AVL Tree
20
92 15
5
10
30
177
0
0 0
011
2 2
3 …
3
value
height
children
10 key
10/11/2019 23
AVL tree operations
• AVL find:
– Same as BST find
• AVL insert:
– First BST insert, then check balance and potentially “fix”
the AVL tree
– Four different imbalance cases
• AVL delete:
– The “easy way” is lazy deletion
– Otherwise, like insert we do the deletion and then have
several imbalance cases
10/11/2019 24
10/11/2019
AVL tree insert
Let b be the node where an imbalance occurs.
Four cases to consider. The insertion is in the
1. left subtree of the left child of b.
2. right subtree of the left child of b.
3. left subtree of the right child of b.
4. right subtree of the right child of b.
Idea: Cases 1 & 4 are solved by a single rotation.
Cases 2 & 3 are solved by a double rotation.b
XVU
Z
ca
1 2 3 425
Insert: detect potential imbalance
1. Insert the new node as in a BST (a new leaf)
2. For each node on the path from the root to the new leaf, the
insertion may (or may not) have changed the node’s height
3. So after recursive insertion in a subtree, detect height imbalance
and perform a rotation to restore balance at that node
All the action is in defining the correct rotations to restore balance
Fact that makes it a bit easier:
– There must be a deepest element that is imbalanced after the
insert (all descendants still balanced)
– After rebalancing this deepest node, every node is balanced
– So at most one node needs to be rebalanced
10/11/2019 26
10/11/2019
Case #1 Example
Insert(6)
Insert(3)
Insert(1)
27
Case #1: Example
10/11/2019 28
Insert(6)
Insert(3)
Insert(1)
Third insertion violates
balance property
• happens to be at
the root
What is the only way to
fix this?
6
3
1
2
1
0
6
3
1
0
60
Fix: Apply “Single Rotation”
• Single rotation: The basic operation we’ll use to rebalance
– Move child of unbalanced node into parent position
– Parent becomes the “other” child (always okay in a BST!)
– Other subtrees move in only way BST allows (next slide)
10/11/2019 29
3
1 600
1
6
3
0
1
2
AVL Property violated here
1
Single Rotation:
1. Rotate between self and child
30
Single Rotation Pseudo-Code
void RotateWithRight(Node root) {
Node temp = root.right
root.right = temp.left
temp.left = root
root.height = max(root.right.height(),
root.left.height()) + 1
temp.height = max(temp.right.height(),
temp.left.height()) + 1
root = temp
}
a
X
Y
b
Z
root
temp
RotateRight brings up the right child
10/11/2019
The example generalized
• Node imbalanced due to insertion somewhere in
left-left grandchild increasing height
– 1 of 4 possible imbalance causes (other three coming)
• First we did the insertion, which would make b imbalanced
10/11/2019 31
b
Z
Y
a
X
h h
h
h+1
h+2 b
Z
Y
a
X
h+1 h
h
h+2
h+3
Notational note:
Oval: a node in the tree
Triangle: a subtree
The general left-left case
• Node imbalanced due to insertion somewhere in
left-left grandchild increasing height
– 1 of 4 possible imbalance causes (other three coming)
• So we rotate at b, using BST facts: X < a < Y < b < Z
10/11/2019 32
• A single rotation restores balance at the node
– To same height as before insertion (so ancestors now balanced)
b
Z
Y
a
X
h+1 h
h
h+2
h+3 a
ZY
bh+1 h
h
h+1
h+2
X
Another example: insert(16)
10/11/2019 33
104
228
15
3 6
19
17 20
24
16
Another example: insert(16)
10/11/2019 34
104
228
15
3 6
19
17 20
24
16
104
8
15
3 6
19
17
2016
22
24
The general right-right case
• Mirror image to left-left case, so you rotate the other way
– Exact same concept, but need different code
10/11/2019 35
a
ZY
X
h
hh+1
h+3
b
h+2 b
Z
Y
a
X
h h
h+1
h+1
h+2
10/11/2019 36
Case #3 Example
Insert(1)
Insert(6)
Insert(3)
Two cases to go
Unfortunately, single rotations are not enough for insertions in the
left-right subtree or the right-left subtree
Simple example: insert(1), insert(6), insert(3)
– First wrong idea: single rotation like we did for left-left
10/11/2019 37
3
6
1
0
1
2
6
1 3
1
0 0
Two cases to go
Unfortunately, single rotations are not enough for insertions in the
left-right subtree or the right-left subtree
Simple example: insert(1), insert(6), insert(3)
– Second wrong idea: single rotation on the child of the
unbalanced node
10/11/2019 38
3
6
1
0
1
2
6
3
1
0
1
2
Sometimes two wrongs make a right
• First idea violated the BST property
• Second idea didn’t fix balance
• But if we do both single rotations, starting with the second, it
works! (And not just for this example.)
Double rotation:
1. Rotate problematic child and grandchild
2. Then rotate between self and new child
10/11/2019 39
3
6
1
0
1
2
6
3
1
0
1
2
00
1
1
3
6
40
Double Rotation Pseudo-Code
void DoubleRotateWithRight(Node root) {
RotateWithLeft(root.right)
RotateWithRight(root)
}
a
Z
c
W
b
XY
a
Z
b
c
X
Y
W
First Rotation
10/11/2019
41
Double Rotation Completed
a
Z
b
c
X
Y
W
a
Z
b
c
XY
W
First Rotation Second Rotation
10/11/2019
The general right-left case
10/11/2019 42
a
X
c
bh-1
h
h
h
VU
h+1
h+2
h+3
Z
a
X
b
h-1
h+1h
h
VU
h+2
h+3
Z
c
h
b
X
h-1
h+1
h
h+1
VU
h+2
Z
c
h
a
h
Comments
• Like in the left-left and right-right cases, the height of the subtree
after rebalancing is the same as before the insert
– So no ancestor in the tree will need rebalancing
• Does not have to be implemented as two rotations; can just do:
10/11/2019 43
a
X
c
bh-1
h
h
h
VU
h+1
h+2
h+3
Z
b
X
h-1
h+1
h
h+1
VU
h+2
Z
c
h
a
h
Easier to remember than you may think:
Move b to grandparent’s position and then put a, c, X, U, V, and
Z in the only legal positions for a BST
The last case: left-right
• Mirror image of right-left
– Again, no new concepts, only new code to write
10/11/2019 44
c
h-1
h
hh
VU
h+1
h+2
h+3
Z
X
a
b
b
X
h-1
h+1
h
h+1
VU
h+2
Z
c
h
a
h
10/11/2019
Insert 5
104
178
15
3 6
16
5
45
10/11/2019
Double rotation, step 1
104
178
15
3 6
16
5
106
178
15
4
3
16
5
46
10/11/2019
Double rotation, step 2
106
178
15
4
3
16
5
10
6 17
8
15
4
3
16
5
47
Insert, summarized
• Insert as in a BST
• Check back up path for imbalance, which will be 1 of 4 cases:
– node’s left-left grandchild is too tall
– node’s left-right grandchild is too tall
– node’s right-left grandchild is too tall
– node’s right-right grandchild is too tall
• Only one case occurs because tree was balanced before insert
• After the appropriate single or double rotation, the smallest-
unbalanced subtree has the same height as before the insertion
– So all ancestors are now balanced
10/11/2019 48
Now efficiency
• Worst-case complexity of find: __________
– Tree is balanced
• Worst-case complexity of insert: __________
– Tree starts balanced
– A rotation is O(1) and there’s an O(log n) path to root
– (Same complexity even without one-rotation-is-enough fact)
– Tree ends balanced
• Worst-case complexity of buildTree: _________
• delete? (see 3 ed. Weiss) requires more rotations: _________
• Lazy deletion? ________________10/11/2019 49
Pros and Cons of AVL Trees
Arguments for AVL trees:
1. All operations logarithmic worst-case because trees are always
balanced
2. Height balancing adds no more than a constant factor to the speed of insert and delete
Arguments against AVL trees:
1. Difficult to program & debug
2. More space for height field
3. Asymptotically faster but rebalancing takes a little time
4. Most large searches are done in database-like systems on disk and
use other structures (e.g., B-trees, our next data structure)
10/11/2019 51
More Examples…
10/11/2019 52
10/11/2019
Insert into an AVL tree: a b e c d
Student Activity 53
10/11/2019 54
9
5
2
11
7
1. single rotation?
2. double rotation?
3. no rotation?
Inserting what integer values
would cause the tree to need
a:
Single and Double Rotations:
13
30
Student Activity
10/11/2019
Easy Insert
2092
155
10
3017
Insert(3)
120
0
100
1 2
3
0
Unbalanced?
55
10/11/2019
Hard Insert
2092
155
10
3017
Insert(33)
3
121
0
100
2 2
3
00
How to fix?
Unbalanced?
56
10/11/2019
Single Rotation
2092
155
10
30173
12
33
1
0
200
2 3
3
10
0
3092
205
10
333
151
0
110
2 2
3
00
17120
57
10/11/2019
Hard Insert
Insert(18)
2092
155
10
30173
121
0
100
2 2
3
00
How to fix?
Unbalanced?
58
10/11/2019
Single Rotation (oops!)
2092
155
10
30173
121
1
200
2 3
3
00
3092
205
10
3
151
1
020
2 3
3
0
17120
180
180
59
10/11/2019
Double Rotation (Step #1)
2092
155
10
30173
121
1
200
2 3
3
00
180
1792
155
10
203
121 200
2 3
3
10
300
180
60
10/11/2019
Double Rotation (Step #2)
1792
155
10
203
121 200
2 3
3
10
300
180
2092
175
10
303
151
0
110
2 2
3
00
120
18
61