You are on page 1of 41

AVL Trees

________________________________________________________ A binary tree is an AVL tree if Each node satisfies BST property key of the node is grater than the key of each node in its left subtree and is smaller than the key of each node in its right subtree

Each node satisfies height-balanced-1-tree property the difference between the heights of the left subtree and right subtree of the node does not exceed one

Binary Search Tree - Best Time


All BST operations are O(d), where d is tree depth minimum d is d log 2N for a binary tree with N nodes
What is the best case tree? What is the worst case tree?

Binary Search Tree


best case running time of BST operations is O(log N)
Worst case running time is O(N)
What happens when you Insert elements in ascending order?
Insert: 1,2,3,4,5 into an empty BST

Why AVL Trees ?


Insert 1, 2, 3, 4 and 5 in the given order 1 2 3 4 5 3 5 1 4

BST after insertions

AVL Tree after insertions

Why AVL Trees ?


Problem: Lack of balance:
compare depths of left and right subtree

Unbalanced degenerate tree.


Search operation takes O(n), which is inefficient as in a list. It is possible that after a number of insert and delete imbalanced n operations a binary tree may become and increase in height. Can we insert and delete elements from BST so that its height is guaranteed to be O(log n)? AVL tree ensures this.

Height of an AVL Tree


Fact: The height of an AVL tree storing n keys is O(log n).

Proof: Let us bound n(h): the minimum number of internal nodes of an AVL tree of eight h. We easily see that n(1) = 1 and n(2) = 2. For n > 2, an AVL tree of height h contains the root node, one AVL x subtree of height n-1 and another of height n-2.
That is, n(h) = 1 + n(h-1) + n(h-2) Knowing n(h-1) > n(h-2), we get n(h) > 2n(h-2). So n(h) > 2n(h-2), n(h) > 4n(h-4), n(h) > 8n(n-6), (by induction), n(h) > 2in(h-2i ) Solving the base case we get: n(h) > 2 h/2-1 Taking logarithms: h < 2log n(h) +2 Thus the height of an AVL tree is O(log n)

N(h-1)

N(h-2)

Balancing Binary Search Trees


Many algorithms exist for keeping binary search trees balanced
Adelson-Velskii and Landis (AVL) trees (height-balanced trees) Splay trees and other self-adjusting trees B-trees and other multiway search trees

Perfect Balance
Want a complete tree after every operation
tree is full except possibly in the lower right

This is expensive
For example, insert 2 in the tree on the left and then rebuild as a complete tree
6 5

4
1 5 8

Insert 2 & complete tree

2
4 6

8
9

AVL - Good but not Perfect Balance


AVL trees are height-balanced binary search trees Balance factor of a node
height left subtree) - height right subtree)

An AVL tree has balance factor calculated at every node


For every node, heights of left and right subtree can differ by no more than 1 Store current heights in each node

Node Heights
Tree A (AVL) height=2 BF=1-0=1 Tree B (AVL) 2

6
1 0 1

6
1

4
0 0

9
0

4
0 0

9 5 8

height of node = h balance factor = hleft-hright


empty height = -1

Node Heights after Insert 7


Tree A (AVL) 2 Tree B (not AVL) 3
balance factor 1-(-1) = 2

6
1 1 1

6 4
0 0 1

4
0 0 0

9 5

9
-1

5
0

height of node = h balance factor = hleft-hright empty height = -1

Insert and Rotation in AVL Trees


Insert operation may cause balance factor to become 2 or 2 for some node
only nodes on the path from insertion point to root node have possibly changed in height So after the Insert, go back up to the root node by node, updating heights If a new balance factor (the difference hlefthright) is 2 or 2, adjust tree by rotation around the node

Single Rotation in an AVL Tree


2 2

6
1 2 1

6
1

4
0 0 1

9
0

4
0

8
0
0

5
0

8 7

Insertions in AVL Trees


Let the node that needs rebalancing be . There are 4 cases: Outside Cases (require single rotation) : 1. Insertion into left subtree of left child of . 2. Insertion into right subtree of right child of . Inside Cases (require double rotation) : 3. Insertion into right subtree of left child of . 4. Insertion into left subtree of right child of .

The rebalancing is performed through four separate rotation algorithms.

AVL Insertion: Outside Case


Consider a valid AVL subtree

j
h h

k
h

AVL Insertion: Outside Case

j k
h+1 h h

Inserting into X destroys the AVL property at node j

Y
X

AVL Insertion: Outside Case

j k
h+1 h

Do a right rotation

Y
X

Single right rotation

j k
h+1 h

Do a right rotation

Y
X

Outside Case Completed

k
h+1
h

Right rotation done! (Left rotation is mirror symmetric)

j
h

AVL property has been restored!

AVL Insertion: Inside Case


Consider a valid AVL subtree

j
h h

k
h

AVL Insertion: Inside Case


Inserting into Y destroys the AVL property at node j

j
k
h+1

Does right rotation restore balance?


h

AVL Insertion: Inside Case

k
h

j
h+1

Right rotation does not restore balance now k is out of balance


h

X Y

AVL Insertion: Inside Case


Consider the structure of subtree Y

j
h h+1

k
h

AVL Insertion: Inside Case


Y = node i and subtrees V and W

j
h

k
h

X
V

h+1

h or h-1

AVL Insertion: Inside Case

j k i V

We will do a left-right double rotation . . .

Double rotation : first rotation

j i k W X V

left rotation complete

Double rotation : second rotation

j i k W X V

Now do a right rotation

Double rotation : second rotation


right rotation complete

i k
h h or h-1

Balance has been restored

j
h

Implementation
balance (1,0,-1) key left right

No need to keep the height; just the difference in height, i.e. the balance factor; this has to be modified on the path of insertion even if you dont perform rotations Once you have performed a rotation (single or double) you wont need to go back up the tree

Single Rotation
RotateFromRight(n : reference node pointer) { p : node pointer; p := n.right; n n.right := p.left; p.left := n; n := p }
You also need to modify the heights or balance factors of n and p X

Insert
Y Z

Double Rotation
Implement Double Rotation in two lines.
DoubleRotateFromRight(n : reference node pointer) { ???? n }

X Z V W

Insertion in AVL Trees


Insert at the leaf (as for all BST)
only nodes on the path from insertion point to root node have possibly changed in height So after the Insert, go back up to the root node by node, updating heights If a new balance factor (the difference hlefthright) is 2 or 2, adjust tree by rotation around the node

Insert in BST
Insert(T : reference tree pointer, x : element) : integer { if T = null then T := new tree; T.data := x; return 1;//the links to //children are null case T.data = x : return 0; //Duplicate do nothing T.data > x : return Insert(T.left, x); T.data < x : return Insert(T.right, x); endcase }

Insert in AVL trees


Insert(T : reference tree pointer, x : element) : { if T = null then {T := new tree; T.data := x; height := 0; return;} case T.data = x : return ; //Duplicate do nothing T.data > x : Insert(T.left, x); if ((height(T.left)- height(T.right)) = 2){ if (T.left.data > x ) then //outside case T = RotatefromLeft (T); else //inside case T = DoubleRotatefromLeft (T);} T.data < x : Insert(T.right, x); code similar to the left case Endcase T.height := max(height(T.left),height(T.right)) +1; return; }

Example of Insertions in an AVL Tree


2

20
0 1

Insert 5, 40 0

10
0

30 25 35

Example of Insertions in an AVL Tree


2

20
1 1 1

20 30
0

10
0
0

30
0

10
0

25

35

5
Now Insert 45

25

35
0

40

Single rotation (outside case)


3 3 2 1

20
1

20 30
0

10
0
0

30
2

10
0

25
Imbalance

35
1 40 0 45

25
0

40 1
0

35
Now Insert 34

45

Double rotation (inside case)


3 3 3 1

20
1

20 35
1 0 25

10
0
0 Imbalance 25

30
2

10
0

40
1 35

5 45 0

30 34

40 1
0

45

Insertion of 34 0

34

AVL Tree Deletion


Similar but more complex than insertion
Rotations and double rotations needed to rebalance Imbalance may propagate upward so that many rotations may be needed.

Pros and Cons of AVL Trees


Arguments for AVL trees:
1. Search is O(log N) since AVL trees are always balanced. 2. Insertion and deletions are also O(logn) 3. The height balancing adds no more than a constant factor to the speed of insertion.

Arguments against using AVL trees:


1. Difficult to program & debug; more space for balance factor. 2. Asymptotically faster but rebalancing costs time. 3. Most large searches are done in database systems on disk and use other structures (e.g. B-trees). 4. May be OK to have O(N) for a single operation if total run time for many consecutive operations is fast (e.g. Splay trees).

IF tree is right heavy { IF tree's right subtree is left heavy { Perform Double Left rotation } ELSE { Perform Single Left rotation } } ELSE IF tree is left heavy { IF tree's left subtree is right heavy { Perform Double Right rotation } ELSE { Perform Single Right rotation } }

You might also like