AVL Tree

39
AVL Tree 1

description

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 - PowerPoint PPT Presentation

Transcript of AVL Tree

AVL Tree

1

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

AVL Non-AVL

1

1

1

1

3

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

• The 4 types:

Solve by single rotation Solve by double rotation6

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 15

2

1

8

4 7

3 6

0

1

1

This node loses AVL property. 5

2

1 84

7

3

6

8

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

Then we insert 4,5

3

2

1

4

5

loses AVL

To be continued

3

2

1

4

3

2

1 4

5

10

• Then we insert 6

3

2

1 4

5

6

loses AVL

rotate

3

2

1

4

5

6

To be continued 11

Then we insert 7

3

2

1

4

5

6

7

loses AVL

rotate

3

2

1

4

5

6

7

12

Double rotation• When Single rotation is useless

a

b

YX

Z

a

b

Y

X

Z

Y does not change level13

a

b

YX

Z

c

Insertion takes place. There must be something in.

a

b

X

Z

Y1 Y2

Loses AVL

14

The first rotation

c

a

b

X

Z

Y1 Y2

c

a

b

X

Z

Y1

Y2

15

the second rotation

c

a

b

X

Z

Y1

Y2

c

b

X

a

ZY1 Y2

16

• 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 14

3

2

1

4

5

6

15

167

14

Loses AVL

3

2

1

4

5

6 15

16

7

14Must jump

rotate

19

• 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

Loses AVL

Loses AVL

36

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