AVL Tree
-
Upload
dieter-morin -
Category
Documents
-
view
28 -
download
1
description
Transcript of AVL Tree
is a binary search tree that• For each node:
– The height of its left and right subtree can only differ at most 1.
– If a tree is an empty tree, we let its height == -1.
• The height of an AVL tree is log N – The exact figure is 1.44log(N+2)-.328
• The height difference constraint leads to:– The minimal number of nodes for a tree of height h, s(h)
= s(h-1)+s(h-2)+1• When h=0, s(h) =1• When h=1, s(h) =2
– This is similar to fibonacci.2
Various functions• All functions are O(log(N)), except insert
and remove -> these may destroy the properties of AVL.
Inserting a new node here destroys AVL.
0
1
1
4
Fix insert+ remove with rotationinsert
– Only nodes on the path from the insertion point to the root have a chance of height change.
– If we follow up from the inserted node, we will eventually find the deepest node that loses its AVL property. We will fix such node. There can only be 4 types of such node.
5
Single rotation after insert
a
b
XY
Z
Pull up
a
b
XY Z
Move the attachment placeto the problem node.
If it is fixed now, no further rotation is needed.7
Example 2• Starting from nothing, we insert 3,2,1
loses AVL
To be continued
3 3
2
3
2
13
2
1
rotate
9
• We do not know whether Y1 or Y2 is the cause. But it does not matter because in the end both of them reduce in level.
It is like letting c release Y1,Y2 and carry a and b instead.
c
a
b
X
Z
Y1 Y2
c
ab
XZ
Y1 Y2Y1, Y2 find places to attach
17
example• Insert 16,15: loses AVL when inserting 15
3
2
1
4
5
6
7
16
15
Loses AVL
rotate
3
2
1
4
5
6
15
167
18
• Insert 13 Loses AVLTwo right moves: single rotation
3
2
1
4
5
6 15
16
7
14
13
3
2
1
4
5
6
15
16
7
14
13
rotate
20
• Insert 12: this is an obvious single rotation
3
2
1
4
5
6
15
16
7
14
13
12
Loses AVL
3
2
1
4
5
6
15
16
7
14
13
12
rotate
21
• Insert 11: another single rotation
3
2
1
4
5
6
15
16
7
14
13
12
11
Loses AVL
rotate
3
2
1
4
5
6 15
16
7
14
13
12
11
22
• Insert 10: another single rotation
1 3
2
4
5
6 15
16
7
14
13
12
11
10
Loses AVL rotate
1 3
2
4
5
6 15
16
7
14
13
12
11
10
23
• Insert 8
• Insert 9: simple double rotation
1 3
2
4
5
6 15
16
7
14
13
12
11
10
8
9
LosesAVL
108
9
24
1. class AvlNode2. {3. // Constructors4. AvlNode( Comparable theElement )5. {6. this( theElement, null, null );7. }
8. AvlNode( Comparable theElement, AvlNode lt, AvlNode rt )9. {10. element = theElement;11. left = lt;12. right = rt;13. height = 0;14. }
15. // Friendly data; accessible by other package routines16. Comparable element; // The data in the node17. AvlNode left; // Left child18. AvlNode right; // Right child19. int height; // Height20. } There will be a method that returns height. So we
do not have to worry if the node we are looking at is null. 25
1. public class AvlTree2. { private AvlNode root;3. /**4. * Construct the tree.5. */6. public AvlTree( )7. {8. root = null;9. }
10. /**11. * Insert into the tree; duplicates are ignored.12. * @param x the item to insert.13. */14. public void insert( Comparable x )15. {16. root = insert( x, root );17. }
26
18. /**19. * Find the smallest item in the tree.20. * @return smallest item or null if empty.21. */22. public Comparable findMin( )23. {24. return elementAt( findMin( root ) );25. }
26. /**27. * Find the largest item in the tree.28. * @return the largest item of null if empty.29. */30. public Comparable findMax( )31. {32. return elementAt( findMax( root ) );33. }
Same asbinary searchTree
27
1. /**2. * Return the height of node t, or -1, if null.3. */4. private static int height( AvlNode t )5. {6. return t == null ? -1 : t.height;7. }
8. /**9. * Return maximum of lhs and rhs.10. */11. private static int max( int lhs, int rhs )12. {13. return lhs > rhs ? lhs : rhs;14. }
Helper functions
28
1. /**2. * Internal method to insert into a subtree.3. * @param x the item to insert.4. * @param t the node that roots the tree.5. * @return the new root.6. */7. private AvlNode insert( Comparable x, AvlNode t )8. {9. if( t == null )10. t = new AvlNode( x, null, null );11. else if( x.compareTo( t.element ) < 0 )12. {13. t.left = insert( x, t.left );14. if( height( t.left ) - height( t.right ) == 2 )15. if( x.compareTo( t.left.element ) < 0 )16. t = rotateWithLeftChild( t );17. else18. t = doubleWithLeftChild( t );19. }20.
Insert
If = =2 is true, x is below.
t
29
21. else if( x.compareTo( t.element ) > 0 )22. {23. t.right = insert( x, t.right );24. if( height( t.right ) - height( t.left ) == 2 )25. if( x.compareTo( t.right.element ) > 0 )26. t = rotateWithRightChild( t );27. else28. t = doubleWithRightChild( t );29. }30. else31. ; // Duplicate; do nothing32. t.height = max( height( t.left ), height( t.right ) ) + 1;33. return t;34. }
t
30
1. /**2. * Rotate binary tree node with left child.
3. * For AVL trees, this is a single rotation for case 1.
4. * Update heights, then return new root.
5. */
6. private static AvlNode rotateWithLeftChild( AvlNode k2 )
7. {
8. AvlNode k1 = k2.left;
9. k2.left = k1.right;
10. k1.right = k2;
11. k2.height = max( height( k2.left ), height( k2.right ) ) + 1;
12. k1.height = max( height( k1.left ), k2.height ) + 1;
13. return k1;
14. }
k2
k1
k2
k1
31
1. /**2. * Rotate binary tree node with right child.3. * For AVL trees, this is a single rotation for case 4.4. * Update heights, then return new root.5. */6. private static AvlNode rotateWithRightChild( AvlNode k1 )7. {8. AvlNode k2 = k1.right;9. k1.right = k2.left;10. k2.left = k1;11. k1.height = max( height( k1.left ), height( k1.right ) ) + 1;12. k2.height = max( height( k2.right ), k1.height ) + 1;13. return k2;14. }
k1
k2 k1
k2
32
1. /**2. * Double rotate binary tree node: first left child3. * with its right child; then node k3 with new left child.4. * For AVL trees, this is a double rotation for case 2.5. * Update heights, then return new root.6. */7. private static AvlNode doubleWithLeftChild( AvlNode k3 )8. {9. k3.left = rotateWithRightChild( k3.left );10. return rotateWithLeftChild( k3 );11. }
k2
k1
X Y1 Y2
k3
Z
k2
k3
k1
X
Z
Y1 Y2
k2
k1
X Y1
Y2
k3
Z
33
1. /**2. * Double rotate binary tree node: first right child3. * with its left child; then node k1 with new right child.4. * For AVL trees, this is a double rotation for case 3.5. * Update heights, then return new root.6. */7. private static AvlNode doubleWithRightChild( AvlNode k1 )8. {9. k1.right = rotateWithLeftChild( k1.right );10. return rotateWithRightChild( k1 );11. }
k2
k1
k3
X
Z
Y1Y2
k2
k3
XY1
Y2
k1
Z
k2
k3
XY1Y2
k1
Z34
Remove a node from AVL
• First, do a normal remove
• Then rebalance, starting from the node just above the removed node up to the root.
• We need to rebalance every node because balancing a child can make its parent loses AVL.
35
private AVLNode basicRemove( Comparable x, AVLNode t ) { if( t == null ) return t; // Item not found; do nothing if( x.compareTo( t.element ) < 0 ) t.left = basicRemove( x, t.left ); else if( x.compareTo( t.element ) > 0 ) t.right = basicRemove( x, t.right ); else if( t.left != null && t.right != null ) // Two children { t.element = findMin( t.right ).element; t.right = basicRemove( t.element, t.right ); } else t = ( t.left != null ) ? t.left : t.right;
t.setHeight(); return t; } This is the same as
BinaryNode’s remove()
37
private AVLNode remove(Comparable x, AVLNode r){
r = basicRemove(x,r);
r = rebalance(r);
return r;
}
public void remove(Comparable x){
root = remove(x, root);
}
private void setHeight(){// this is in AVLNode
height = 1 + Math.max(height(left), height(right));
}
private static int height(AVLNode n){ // this is in AVLNode
return (n == null ? -1 : n.height);
} 38
private AVLNode rebalance(AVLNode r){
if (r == null) return r;
int balance = balanceValue(r);
if (balance == 2){//left hand side has more nodes than it should have
if (balanceValue(r.left) ==-1)
r.left = rotateWithRightChild(r.left);
r = rotateWithLeftChild(r);
} else if (balance == -2){//right hand side has more nodes than it should have
if (balanceValue(r.right) ==1)
r.right = rotateWithLeftChild(r.right);
r = rotateWithRightChild(r);
}
r.setHeight();
return r;
}
public int balanceValue(AvlNode t){
return height(t.left) – height(t.right);
} 39