Workshop Leader Interest Meeting Today 5:15PM LAS – Basement of Lattimore.
-
date post
21-Dec-2015 -
Category
Documents
-
view
213 -
download
0
Transcript of Workshop Leader Interest Meeting Today 5:15PM LAS – Basement of Lattimore.
Workshop Leader Interest Meeting
Today 5:15PM LAS – Basement of Lattimore
AVL Trees
CSC 172
SPRING 2004
LECTURE 17
A PROBLEM WITH BSTs
Common operations on balanced BST are O(log(n))
Alas, when the tree goes out of balance, performance degrades (worst case : chain O(n))
There are several data structures that modify the BST to maintain balance.
BST Structure : Log & Linear
Permutations of 1,2,3
AVL Trees
The first balanced binary search tree
Named after discoverers Adelson-Velskii and Landis.
DEFINITION:An AVL tree is a binary search tree with the additional
balance property that, for any node in the tree, the height of the left and right subtrees can differ by at most 1. (Height of an empty subtree is –1).
12
8 16
2 6
4 10 14
AN AVL TREE
What if we insert “7”?-1 -1 -1 -1
-1 -1 -1 -1
-1
0 0
001
12What is the height?
3
12
8 16
2 6
4 10 14
NOT AN AVL TREE
-1 -1
-1 -1
-1 -1 -1 -10 1
002
13
4
-1
7
-1 0
Out of balance
AVL THEOREMAn AVL tree of n element has height O(log n)
In fact, An AVL tree of height H has at least FH+3 –1 nodes, where Fi is the ith Fibonacci number
AVL THEOREMLet SH be the size of smallest AVL tree of height H.
Clearly S0=1 and S1=2
SH must have subtrees of height H-1 and H-2
These subtrees must have fewest nodes for height
So, SH = SH-1 + SH-2 + 1
Minimum number AVL trees are Fibonacci trees
Smallest AVL Tree of height H
SH-
1
H-1SH-
2
H-2
H
SH = FH+3 – 1
FH+3 – 1 >= (3/2)H // do this as exercise
Hint: (3/2)H-1+(3/2)H=(3/2)H-2(3/2 + 1) > (3/2)H-2(9/4)
SH >= (3/2)H
Log2(SH) >= H Log2(3/2)
H <= 1.75 Log2(SH)
Adds can unbalance a BST
Only nodes on the path from the root to the insertion point can have their balances altered
If we restore the unbalance node, we balance the tree
12
8 16
2 6
4 10 14
AN AVL TREE
What if we insert “15”?
-1 -1 -1 -1
-1 -1 -1 -1
-1
0 0
001
12
3
If we insert 7We unbalance the whole tree
12
8 16
2 6
4 10 14
AN AVL TREE
What if we insert “15”?
-1 -1 -1 -1
-1 -1 -1
-1
0 0
101
22
3
If we insert 7We unbalance the whole tree
15-1 -1
0
4 cases
1. Insertion in left sub-tree of left child
2. Insertion in right sub-tree of left child
3. Insertion in left sub-tree of right child
4. Insertion in right sub-tree of right child
1 & 4 are symmetric
2 & 3 are symmetric
Cases 1 & 4
A B
C
k1
k2Insertion extends Tree ‘A’
HH-2
H-2 H-2
Cases 1 & 4
A B
C
k1
k2Insertion extends Tree ‘A’
H-2
H-1 H-2
“Rotation” fixesbalance
Cases 1 & 4
AB C
k2
k1Insertion extends Tree ‘A’
H-2H-1 H-2
“Rotation” fixesbalance
H
Cases 2 & 3
A B
C
k1
k2Insertion extends Tree ‘B’
HH-2
H-2 H-2
Cases 2 & 3
A B
C
k1
k2Insertion extends Tree ‘B’
H-2
H-2 H-1
Cases 2 & 3
AB C
k2
k1Insertion extends Tree ‘B’
H-2H-2 H-1
“Rotation” Does not fixbalance
Double Rotation
If x is out of balance for cases 2&3
1. Rotate between X’s child and grandchild
2. Rotate between X and it’s new child
Cases 2 & 3
A B
C
k1
k2Insertion extends Tree ‘B’
HH-2
H-2 H-2
Cases 2 & 3
A C
D
k1
k2Insertion extends Tree ‘B’ or ‘C’
HH-2
H-2 H-3
k3
B
Cases 2 & 3
A C
D
k1
k2Insertion extends Tree ‘B’ or ‘C’
H-2
H-2 H-2
k3
B
Rotate grandchildWith child
Cases 2 & 3
AC
D
k3
k2Insertion extends Tree ‘B’ or ‘C’
H-2
H-2
H-2
k1
B
Rotate grandchildWith child
Rotate X with new child
Cases 2 & 3
A C D
k2
k3Insertion extends Tree ‘B’ or ‘C’
H-2
H-2
H-2
k1
B
Rotate grandchildWith child
Rotate X with new child
Implementation
Insert
Fixup
Rotate
Need to keep track of balance
Rotationprivate void rotateLeft(Node p) {
Node r = p.right;p.right = r.left;if (r.left != null) r.left.parent = p;r.parent = p.parent;if (p.parent == null) {root = r; r.parent = null;}else if (p.parent.left == p) p.parent.left = r;else p.parent.right = r;r.left = p;p.parent = r;
}
element left right parentroot
50
80
element left right parentroot
50
80
90
r
Entry r = p.right;
p
element left right parentroot
50
80
90
r
Entry r = p.right;p.right = r.left;
p
element left right parentroot
50
80
90
r
Entry r = p.right;p.right = r.left;if (r.left != null) r.left.parent = p;if (p.parent == null)root = r; r.parent = p.parent;
p
element left right parentroot
50
80
90
r
Entry r = p.right;p.right = r.left;if (r.left != null) r.left.parent = p;r.parent = p.parent;if (p.parent == null) root = r;else if …else …r.left = p;
p
element left right parentroot
50
80
90
r
Entry r = p.right;p.right = r.left;if (r.left != null) r.left.parent = p;r.parent = p.parent;if (p.parent == null){ root = r; ..}else if …else …r.left = p;p.parent = r;
p
Node classprivate static class Node {
Object element;char balanceFactor = ‘=‘; // new nodes are balanced// we could set this to R or L indicating child with > heightNode left = null, right = null, parent;Node (Object element, Entry parent) {
this.element = element;this.parent = parent;
}}
50
R
20
L
10
=
80
R
70
=
100
=
92
=
50
=
public boolen add(Object o){
if (root == null) {
root = new Node(o,null);
size++;
return true;
}// empty tree
else {
Node temp = root,
ancestor = null; // we keep track of nearest unbalanced ancestor
int comp;
while (true) {
comp = ((Comparable)o).compareTo(temp.element);
if (comp == 0) return false;
if (comp < 0) {
if (temp.balanceFactor != ‘=‘) ancestor = temp;
if (temp.left != null) temp = temp.left;
else {
temp.left = new Entry(o,temp);
fixAfterInsertion(ancestor,temp.left);
size++;
}
}// comp < 0
else { // comp > 0
if (temp.balanceFactor != ‘=‘) ancestor = temp;
if (temp.right != null) temp = temp.right;
else {
temp.rig = new Node(o,temp);
fixAfterInsertion(ancestor,temp.right);
size++;
}
}// comp < 0
}// while
}// root not null
}//method add
Adjusting paths50
=
25
=
15
=
70
=
60
=
30
=
55
=
90
=
Adjusting paths50
R
25
=
15
=
70
L
60
L
30
=
55
=
90
=
protected void adjustPath(Entry to, Entry inserted) {
Object o = inserted.element;
Node temp = inserted.parent;
while (temp != to) {
if (((Comparable)o).compareTo(temp.element)<0)
temp.balanceFactor = ‘L’;
else
temp.balanceFactor = ‘R’;
temp= temp.parent
}// while
} //adjust path
protected void fixAfterInsertion(Node ancestor, Entry inserted) {
Object o = inserted element;
if (ancestor == null) {
if (((Comparable)o).compareTo(root.element)<0)
root.balanceFactor = ‘L’;
else
root.balanceFactor = ‘R’;
adjustPath(root,inserted);
} // Case 1: all ancestor of inserted element have ‘=‘ balanceFactor
if ((ancestor.balanceFactor == ‘L’ &&
((Comparable)o).compareTo(ancestor.element)>0)||
(ancestor.balanceFactor == ‘R’ &&
((Comparable)o).compareTo(ancestor.element)<0)){
ancestor.balanceFactor = ‘=’;
adjustPath(ancestor,inserted);
} // Case 2: insertion causes ancestor’s balanceFactor to ‘=‘
if ((ancestor.balanceFactor == ‘R’ &&
((Comparable)o).compareTo(ancestor.right.element)>0){
ancestor.balanceFactor = ‘=’;
rotateLeft(ancestor);
adjustPath(ancestor.parent,inserted);
} // Case 3: ancestor’s balance factor = ‘R’
// and o > ancestor’s right child
if ((ancestor.balanceFactor == ‘L’ &&
((Comparable)o).compareTo(ancestor.left.element)<0){
ancestor.balanceFactor = ‘=’;
rotateRight(ancestor);
adjustPath(ancestor.parent,inserted);
} // Case 4: ancestor’s balance factor = ‘L’
// and o < ancestor’s right child
if (ancestor.balanceFactor == ‘L’ &&
((Comparable)o).compareTo(ancestor.left.element)>0){
rotateLeft(ancestor.left);
rotateRight(ancestor);
adjustLeftRight(ancestor,inserted);
} // Case 5: ancestor’s balanceFactor = ‘L’
// and o > ancestor’s left child
else{
rotateRight(ancestor.right);
rotateLeft(ancestor);
adjustRightLeft(ancestor,inserted);
} // Case 6: ancestor’s balanceFactor = ‘R’
// and o < ancestor’s right child
}// fixAfterInsertion
protected void adjustLeftRight(Entry ancestor, Entry inserted) {
Object o = inserted.element;
if (ancestor.parent == inserted) ancestor.balanceFactor = ‘=‘;
else if (((Comparable)o).compareTo(ancestor.parent.element)<0){
ancestor.balanceFactor = ‘R’;
adjustPath(ancestor.parent.left,inserted);
}// o < ancestor’s parent
else {
ancestor.balanceFactor = ‘=’;
ancestor.parent.left.balanceFactor = ‘L’;
adjustPath(ancestor,inserted);
}// while
} //adjustLeftRight
AdjustLeftRight Case 1
50
L
30
=
40
=
50
=
40
=
30
=
AdjustLeftRight Case250
L
10
=5
=
15
=35
=
40
=30
=
45
=
20
=
90
=
70
=
100
=Rotate Left around 20Right around 50
AdjustLeftRight Case240
=
10
=5
=
15
=
30
R35
=
20
=
50
R
45
=
90
=70
=
100
=
AdjustLeftRight Case350
L
10
=5
=
15
=42
=
40
=30
=
45
=
20
=
90
=
70
=
100
=Rotate Left around 20Right around 50
AdjustLeftRight Case340
=
10
=5
=
15
=
30
=42
=
20
L
50
=
45
L
90
=70
=
100
=
protected void adjustRightLeft(Entry ancestor, Entry inserted) {
Object o = inserted.element;
if (ancestor.parent == inserted) ancestor.balanceFactor = ‘=‘;
else if (((Comparable)o).compareTo(ancestor.parent.element)>0){
ancestor.balanceFactor = ‘L’;
adjustPath(ancestor.parent.right,inserted);
}// o < ancestor’s parent
else {
ancestor.balanceFactor = ‘=’;
ancestor.parent.right.balanceFactor = ‘R’;
adjustPath(ancestor,inserted);
}// while
} //adjustRightLeft