ECE 250 Algorithms and Data Structures AVL Trees

  • Slides: 100
Download presentation
ECE 250 Algorithms and Data Structures AVL Trees Douglas Wilhelm Harder, M. Math. LEL

ECE 250 Algorithms and Data Structures AVL Trees Douglas Wilhelm Harder, M. Math. LEL Department of Electrical and Computer Engineering University of Waterloo, Ontario, Canada Copyright © 2006 -11 by Douglas Wilhelm Harder. All rights reserved.

AVL Trees Outline Background Define balance Maintaining balance within a tree – AVL trees

AVL Trees Outline Background Define balance Maintaining balance within a tree – AVL trees – Difference of heights – Rotations to maintain balance 2

AVL Trees Background From previous lectures: – Binary search trees store linearly ordered data

AVL Trees Background From previous lectures: – Binary search trees store linearly ordered data – Best case height: Q(ln(n)) – Worst case height: O(n) Requirement: – Define and maintain a balance to ensure Q(ln(n)) height 3

AVL Trees Prototypical Examples These two examples demonstrate how we can correct for imbalances:

AVL Trees Prototypical Examples These two examples demonstrate how we can correct for imbalances: starting with this tree, add 1: 4

AVL Trees Prototypical Examples This is more like a linked list; however, we can

AVL Trees Prototypical Examples This is more like a linked list; however, we can fix this… 5

AVL Trees Prototypical Examples Promote 2 to the root, demote 3 to be 2’s

AVL Trees Prototypical Examples Promote 2 to the root, demote 3 to be 2’s right child, and 1 remains the left child of 2 6

AVL Trees Prototypical Examples The result is a perfect, though trivial tree 7

AVL Trees Prototypical Examples The result is a perfect, though trivial tree 7

AVL Trees Prototypical Examples Alternatively, given this tree, insert 2 8

AVL Trees Prototypical Examples Alternatively, given this tree, insert 2 8

AVL Trees Prototypical Examples Again, the product is a linked list; however, we can

AVL Trees Prototypical Examples Again, the product is a linked list; however, we can fix this, too 9

AVL Trees Prototypical Examples Promote 2 to the root, and assign 1 and 3

AVL Trees Prototypical Examples Promote 2 to the root, and assign 1 and 3 to be its children 10

AVL Trees Prototypical Examples The result is, again, a perfect tree These examples may

AVL Trees Prototypical Examples The result is, again, a perfect tree These examples may seem trivial, but they are the basis for the corrections in the next data structure we will see: AVL trees 11

AVL Trees We will focus on the first strategy: AVL trees – Named after

AVL Trees We will focus on the first strategy: AVL trees – Named after Adelson-Velskii and Landis Balance is defined by comparing the height of the two sub-trees of a node – An empty tree has height – 1 – A tree with a single node has height 0 12

AVL Trees A binary search tree is said to be AVL balanced if: –

AVL Trees A binary search tree is said to be AVL balanced if: – The difference in the heights between the left and right sub-trees is at most 1, and – Both sub-trees are themselves AVL trees 13

AVL Trees AVL trees with 1, 2, 3, and 4 nodes: 14

AVL Trees AVL trees with 1, 2, 3, and 4 nodes: 14

AVL Trees Here is a larger AVL tree (42 nodes): 15

AVL Trees Here is a larger AVL tree (42 nodes): 15

AVL Trees The root node is AVL-balanced: – Both sub-trees are of height 4:

AVL Trees The root node is AVL-balanced: – Both sub-trees are of height 4: 16

AVL Trees All other nodes (e. g. , AF and BL) are AVL balanced

AVL Trees All other nodes (e. g. , AF and BL) are AVL balanced – The sub-trees differ in height by at most one 17

AVL Trees Height of an AVL Tree By the definition of complete trees, any

AVL Trees Height of an AVL Tree By the definition of complete trees, any complete binary search tree is an AVL tree Thus an upper bound on the number of nodes in an AVL tree of height h a perfect binary tree with 2 h + 1 – 1 nodes – What is an lower bound? 18

AVL Trees Height of an AVL Tree Let F(h) be the fewest number of

AVL Trees Height of an AVL Tree Let F(h) be the fewest number of nodes in a tree of height h From a previous slide: F(0) = 1 F(1) = 2 F(2) = 4 Can we find F(h)? 19

AVL Trees Height of an AVL Tree The worst-case AVL tree of height h

AVL Trees Height of an AVL Tree The worst-case AVL tree of height h would have: – A worst-case AVL tree of height h – 1 on one side, – A worst-case AVL tree of height h – 2 on the other, and – The root node We get: F(h) = F(h – 1) + 1 + F(h – 2) 20

AVL Trees Height of an AVL Tree This is a recurrence relation: The solution?

AVL Trees Height of an AVL Tree This is a recurrence relation: The solution? 21

AVL Trees Height of an AVL Tree Use Maple: > rsolve( {F(0) = 1,

AVL Trees Height of an AVL Tree Use Maple: > rsolve( {F(0) = 1, F(1) = 2, F(h) = 1 + F(h - 1) + F(h - 2)}, F(h) ); > asympt( %, h ); 22

AVL Trees Height of an AVL Tree This is approximately F(h) ≈ 1. 8944

AVL Trees Height of an AVL Tree This is approximately F(h) ≈ 1. 8944 f h where f ≈ 1. 6180 is the golden ratio – That is, F(h) = W(f h) Thus, we may find the maximum value of h for a given n: logf( n / 1. 8944 ) = logf( n ) – 1. 3277 23

AVL Trees Height of an AVL Tree In this example, n = 88, the

AVL Trees Height of an AVL Tree In this example, n = 88, the worst- and best-case scenarios differ in height by only 2 24

AVL Trees Height of an AVL Tree If n = 106, the bounds on

AVL Trees Height of an AVL Tree If n = 106, the bounds on h are: – The minimum height: – the maximum height : log 2( 106 ) – 1 ≈ 19 logf( 106 / 1. 8944 ) < 28 25

AVL Trees Maintaining Balance To maintain AVL balance, observe that: – Inserting a node

AVL Trees Maintaining Balance To maintain AVL balance, observe that: – Inserting a node can increase the height of a tree by at most 1 – Removing a node can decrease the height of a tree by at most 1 26

AVL Trees Maintaining Balance Insert either 15 or 42 into this AVL tree 27

AVL Trees Maintaining Balance Insert either 15 or 42 into this AVL tree 27

AVL Trees Maintaining Balance Inserting 15 does not change any heights 28

AVL Trees Maintaining Balance Inserting 15 does not change any heights 28

AVL Trees Maintaining Balance Inserting 42 changes the height of two of the sub-trees

AVL Trees Maintaining Balance Inserting 42 changes the height of two of the sub-trees 29

AVL Trees Maintaining Balance To calculate changes in height, the member function must run

AVL Trees Maintaining Balance To calculate changes in height, the member function must run in O(1) time Our implementation of height is O(n): template <typename Comp> int Binary_search_node<Comp>: : height() const { return max( ( left() == 0 ) ? 0 : 1 + left()->height(), ( right() == 0 ) ? 0 : 1 + right()->height() ); } 30

AVL Trees Maintaining Balance Introduce a member variable int tree_height; The member function is

AVL Trees Maintaining Balance Introduce a member variable int tree_height; The member function is now: template <typename Comp> int Binary. Search. Node<Comp>: : height() const { return tree_height; } 31

AVL Trees Maintaining Balance Only insert and erase may change the height – This

AVL Trees Maintaining Balance Only insert and erase may change the height – This is the only place we need to update the height – These algorithms are already recursive 32

AVL Trees Insert template <typename Comp> void AVL_node<Comp>: : insert( const Comp & obj

AVL Trees Insert template <typename Comp> void AVL_node<Comp>: : insert( const Comp & obj ) { if ( obj < element ) { if ( left() == 0 ) { left_tree = new AVL_node<Comp>( obj ); tree_height = 1; } else { left()->insert( obj ); tree_height = max( tree_height, 1 + left()->height() ); } } else if ( obj > element ) { //. . . } } 33

AVL Trees Maintaining Balance Using the same, tree, we mark the stored heights: 34

AVL Trees Maintaining Balance Using the same, tree, we mark the stored heights: 34

AVL Trees Maintaining Balance Again, consider inserting 42 – We update the heights of

AVL Trees Maintaining Balance Again, consider inserting 42 – We update the heights of 38 and 44: 35

AVL Trees Maintaining Balance If a tree is AVL balanced, for an insertion to

AVL Trees Maintaining Balance If a tree is AVL balanced, for an insertion to cause an imbalance: – The heights of the sub-trees must differ by 1 – The insertion must increase the height of the deeper sub-tree by 1 36

AVL Trees Maintaining Balance Starting with our sample tree 37

AVL Trees Maintaining Balance Starting with our sample tree 37

AVL Trees Maintaining Balance Inserting 23: – 4 nodes change height 38

AVL Trees Maintaining Balance Inserting 23: – 4 nodes change height 38

AVL Trees Maintaining Balance Insert 9 – Again 4 nodes change height 39

AVL Trees Maintaining Balance Insert 9 – Again 4 nodes change height 39

AVL Trees Maintaining Balance In both cases, there is one deepest node which becomes

AVL Trees Maintaining Balance In both cases, there is one deepest node which becomes unbalanced 40

AVL Trees Maintaining Balance Other nodes may become unbalanced – E. g. , 36

AVL Trees Maintaining Balance Other nodes may become unbalanced – E. g. , 36 in the left tree is also unbalanced We only have to fix the imbalance at the lowest point 41

AVL Trees Maintaining Balance Inserting 23 – Lowest imbalance at 17 – The root

AVL Trees Maintaining Balance Inserting 23 – Lowest imbalance at 17 – The root is also unbalanced 42

AVL Trees Maintaining Balance A quick rearrangement solves all the imbalances at all levels

AVL Trees Maintaining Balance A quick rearrangement solves all the imbalances at all levels 43

AVL Trees Maintaining Balance Insert 31 – Lowest imbalance at 17 44

AVL Trees Maintaining Balance Insert 31 – Lowest imbalance at 17 44

AVL Trees Maintaining Balance A simple rearrangement solves the imbalances at all levels 45

AVL Trees Maintaining Balance A simple rearrangement solves the imbalances at all levels 45

AVL Trees Maintaining Balance: Case 1 Consider the following setup – Each blue triangle

AVL Trees Maintaining Balance: Case 1 Consider the following setup – Each blue triangle represents a tree of height h 46

AVL Trees Maintaining Balance: Case 1 Insert a into this tree: it falls into

AVL Trees Maintaining Balance: Case 1 Insert a into this tree: it falls into the left subtree BL of b – Assume BL remains balanced – Thus, the tree rooted at b is also balanced 47

AVL Trees Maintaining Balance: Case 1 However, the tree rooted at node f is

AVL Trees Maintaining Balance: Case 1 However, the tree rooted at node f is now unbalanced – We will correct the imbalance at this node 48

AVL Trees Maintaining Balance: Case 1 We will modify these three pointers – At

AVL Trees Maintaining Balance: Case 1 We will modify these three pointers – At this point, this references the unbalanced root node f 49

AVL Trees Maintaining Balance: Case 1 Specifically, we will rotate these two nodes around

AVL Trees Maintaining Balance: Case 1 Specifically, we will rotate these two nodes around the root: – Recall the first prototypical example – Promote node b to the root and demote node f to be the right child of b AVL_node<Comp> *pl = left(), *BR = left()->right(); 50

AVL Trees Maintaining Balance: Case 1 This requires the address of node f to

AVL Trees Maintaining Balance: Case 1 This requires the address of node f to be assigned to the right_tree member variable of node b AVL_node<Comp> *pl = left(), *BR = left()->right(); pl->right_tree = this; 51

AVL Trees Maintaining Balance: Case 1 Assign any former parent of node f to

AVL Trees Maintaining Balance: Case 1 Assign any former parent of node f to the address of node b Assign the address of the tree BR to left_tree of node f AVL_node<Comp> *pl = left(), *BR = left()->right(); pl->right_tree = this; ptr_to_this = pl; left_node = BR; 52

AVL Trees Maintaining Balance: Case 1 The nodes b and f are now balanced

AVL Trees Maintaining Balance: Case 1 The nodes b and f are now balanced and all remaining nodes of the subtrees are in their correct positions 53

AVL Trees Maintaining Balance: Case 1 Additionally, height of the tree rooted at b

AVL Trees Maintaining Balance: Case 1 Additionally, height of the tree rooted at b equals the original height of the tree rooted at f – Thus, this insertion will no longer affect the balance of any ancestors all the way back to the root 54

AVL Trees Maintaining Balance: Case 2 Alternatively, consider the insertion of c where b

AVL Trees Maintaining Balance: Case 2 Alternatively, consider the insertion of c where b < c < f into our original tree 55

AVL Trees Maintaining Balance: Case 2 Assume that the insertion of c increases the

AVL Trees Maintaining Balance: Case 2 Assume that the insertion of c increases the height of BR – Once again, f becomes unbalanced 56

AVL Trees Maintaining Balance: Case 2 Unfortunately, the previous rotation does not fix the

AVL Trees Maintaining Balance: Case 2 Unfortunately, the previous rotation does not fix the imbalance at the root of this subtree: the new root, b, remains unbalanced 57

AVL Trees Maintaining Balance: Case 2 Unfortunately, this does not fix the imbalance at

AVL Trees Maintaining Balance: Case 2 Unfortunately, this does not fix the imbalance at the root of this subtree 58

AVL Trees Maintaining Balance: Case 2 Re-label the tree by dividing the left subtree

AVL Trees Maintaining Balance: Case 2 Re-label the tree by dividing the left subtree of f into a tree rooted at d with two subtrees of height h – 1 59

AVL Trees Maintaining Balance: Case 2 Now an insertion causes an imbalance at f

AVL Trees Maintaining Balance: Case 2 Now an insertion causes an imbalance at f – The addition of either c or e will cause this 60

AVL Trees Maintaining Balance: Case 2 We will reassign the following pointers AVL_node<Comp> *pl

AVL Trees Maintaining Balance: Case 2 We will reassign the following pointers AVL_node<Comp> *pl = left(), *plr = left()->right(), *LRL = left()->right()->left(), *LRR = left()->right(); 61

AVL Trees Maintaining Balance: Case 2 Specifically, we will order these three nodes as

AVL Trees Maintaining Balance: Case 2 Specifically, we will order these three nodes as a perfect tree – Recall the second prototypical example 62

AVL Trees Maintaining Balance: Case 2 To achieve this, b and f will be

AVL Trees Maintaining Balance: Case 2 To achieve this, b and f will be assigned as children of the new root d AVL_node<Comp> *pl = left(), *plr = left()->right(), *LRL = left()->right()->left(), *LRR = left()->right(); plr->left_tree = pl; plr->right_tree = this; 63

AVL Trees Maintaining Balance: Case 2 We also have to connect the two subtrees

AVL Trees Maintaining Balance: Case 2 We also have to connect the two subtrees and original parent of f AVL_node<Comp> *pl = left(), *plr = left()->right(), *LRL = left()->right()->left(), *LRR = left()->right(); plr->left_tree = pl; plr->right_tree = this; ptr_to_this = lrptr; pl->right_tree = LRL; left_tree = LRR; 64

AVL Trees Maintaining Balance: Case 2 Now the tree rooted at d is balanced

AVL Trees Maintaining Balance: Case 2 Now the tree rooted at d is balanced 65

AVL Trees Maintaining Balance: Case 2 Again, the height of the root did not

AVL Trees Maintaining Balance: Case 2 Again, the height of the root did not change 66

AVL Trees Rotations: Summary There are two symmetric cases to those we have examined:

AVL Trees Rotations: Summary There are two symmetric cases to those we have examined: – insertions into either the • left-left sub-tree or the right-right sub-tree which cause an imbalance require a single rotation to balance the node – insertions into either the • left-right sub-tree or the right-left sub-tree which cause an imbalance require two rotations to balance the node 67

AVL Trees Insert (Implementation) template <typename Comp> void AVL_node<Comp>: : insert( const Comp &

AVL Trees Insert (Implementation) template <typename Comp> void AVL_node<Comp>: : insert( const Comp & obj ) { if ( obj < element ) { if ( left() == 0 ) { // cannot cause an AVL imbalance left_tree = new AVL_node<Comp>( obj ); tree_height = 1; } else { left()->insert( obj ); if ( left()->height() - right()->height() == 2 ) { // determine if it is a left-left or left-right insertion // perform the appropriate rotation } } } else if ( obj > element ) { //. . . 68

AVL Trees Insertion (Implementation) Comments: – – – All the rotation statements are Q(1)

AVL Trees Insertion (Implementation) Comments: – – – All the rotation statements are Q(1) An insertion requires at most 2 rotations All insertions are still Q(ln(n)) It is possible to tighten the previous code Aside • if you want to explicitly rotate the nodes A and B, you must also pass a reference to the parent pointer as an argument: insert( Object obj, AVL_node<Comp> * & parent ) 69

AVL Trees Example Rotations Consider the following AVL tree 70

AVL Trees Example Rotations Consider the following AVL tree 70

AVL Trees Example Rotations • Usually an insertion does not require a rotation 71

AVL Trees Example Rotations • Usually an insertion does not require a rotation 71

AVL Trees Example Rotations • Inserting 71 cause a right-right imbalance at 61 72

AVL Trees Example Rotations • Inserting 71 cause a right-right imbalance at 61 72

AVL Trees Example Rotations • A single rotation balances the tree 73

AVL Trees Example Rotations • A single rotation balances the tree 73

AVL Trees Example Rotations • The insertion of 46 causes a right-left imbalance at

AVL Trees Example Rotations • The insertion of 46 causes a right-left imbalance at 42 74

AVL Trees Example Rotations • First, we rotate outwards with 43 -48 75

AVL Trees Example Rotations • First, we rotate outwards with 43 -48 75

AVL Trees Example Rotations • We balance the tree by rotating 42 -43 76

AVL Trees Example Rotations • We balance the tree by rotating 42 -43 76

AVL Trees Example Rotations • Inserting 37 causes a left-left imbalance at 42 77

AVL Trees Example Rotations • Inserting 37 causes a left-left imbalance at 42 77

AVL Trees Example Rotations • A single rotation around 38 -42 balances the tree

AVL Trees Example Rotations • A single rotation around 38 -42 balances the tree 78

AVL Trees Example Rotations • Inserting 54 causes a left-right imbalance at 48 79

AVL Trees Example Rotations • Inserting 54 causes a left-right imbalance at 48 79

AVL Trees Example Rotations • We start with a rotation around 48 -43 80

AVL Trees Example Rotations • We start with a rotation around 48 -43 80

AVL Trees Example Rotations • We balance the tree by rotating 48 -55 81

AVL Trees Example Rotations • We balance the tree by rotating 48 -55 81

AVL Trees Example Rotations • Finally, we insert 99, causing a right-right imbalance at

AVL Trees Example Rotations • Finally, we insert 99, causing a right-right imbalance at the root 36 82

AVL Trees Example Rotations • A single rotation balances the tree • Note the

AVL Trees Example Rotations • A single rotation balances the tree • Note the weight has been shifted to the left sub-tree 83

AVL Trees Erase Removing a node from an AVL tree may cause more than

AVL Trees Erase Removing a node from an AVL tree may cause more than one AVL imbalance – Like insert, erase must check after it has been successfully called on a child to see if it caused an imbalance – Unfortunately, it may cause h/2 imbalances that must be corrected • Insertions will only cause one imbalance that must be fixed 84

AVL Trees Erase Consider the following AVL tree 85

AVL Trees Erase Consider the following AVL tree 85

AVL Trees Erase Suppose we erase the front node: 1 86

AVL Trees Erase Suppose we erase the front node: 1 86

AVL Trees Erase While its previous parent, 2, is not unbalanced, its grandparent 3

AVL Trees Erase While its previous parent, 2, is not unbalanced, its grandparent 3 is – The imbalance is in the right-right subtree 87

AVL Trees Erase We can correct this with a simple rotation 88

AVL Trees Erase We can correct this with a simple rotation 88

AVL Trees Erase The node of that subtree, 5, is now balanced 89

AVL Trees Erase The node of that subtree, 5, is now balanced 89

AVL Trees Erase Recursing to the root, however, 8 is also unbalanced – This

AVL Trees Erase Recursing to the root, however, 8 is also unbalanced – This is a right-left imbalance 90

AVL Trees Erase Promoting 11 to the root corrects the imbalance 91

AVL Trees Erase Promoting 11 to the root corrects the imbalance 91

AVL Trees Erase At this point, the node 11 is balanced 92

AVL Trees Erase At this point, the node 11 is balanced 92

AVL Trees Erase Still, the root node is unbalanced – This is a right-right

AVL Trees Erase Still, the root node is unbalanced – This is a right-right imbalance 93

AVL Trees Erase Again, a simple rotation fixes the imbalance 94

AVL Trees Erase Again, a simple rotation fixes the imbalance 94

AVL Trees Erase The resulting tree is now AVL balanced – Note, few erases

AVL Trees Erase The resulting tree is now AVL balanced – Note, few erases will require one rotation, even fewer will require more than one 95

AVL Trees as Arrays? We previously saw that: – Complete tree can be stored

AVL Trees as Arrays? We previously saw that: – Complete tree can be stored using an array using Q(n) memory – An arbitrary tree of n nodes requires O(2 n) memory Is it possible to store an AVL tree as an array and not require exponentially more memory? 96

AVL Trees as Arrays? Recall that in the worst case, an AVL tree of

AVL Trees as Arrays? Recall that in the worst case, an AVL tree of n nodes has a height at most logf(n) – 1. 3277 Such a tree requires an array of size 2 logf(n) – 1. 3277 + 1 – 1 We can rewrite this as 2– 0. 3277 nlogf(2) ≈ 0. 7968 n 1. 44 Thus, we would require O(n 1. 44) memory 97

AVL Trees as Arrays? While the polynomial behaviour of n 1. 44 is not

AVL Trees as Arrays? While the polynomial behaviour of n 1. 44 is not as bad as exponential behaviour, it is still reasonably sub-optimal when compared to the linear growth associated with nodebased trees Here we see n and n 1. 44 on [0, 1000] 98

AVL Trees Summary • In this topic we have covered: – Insertions and removals

AVL Trees Summary • In this topic we have covered: – Insertions and removals are like binary search trees – With each insertion or removal there is at most one correction required • a single rotation, or • a double rotation; which runs in O(1) time – Depth is O( ln(n) ) ∴ all operations are O( ln(n) ) 99

AVL Trees Usage Notes • • These slides are made publicly available on the

AVL Trees Usage Notes • • These slides are made publicly available on the web for anyone to use If you choose to use them, or a part thereof, for a course at another institution, I ask only three things: – that you inform me that you are using the slides, – that you acknowledge my work, and – that you alert me of any mistakes which I made or changes which you make, and allow me the option of incorporating such changes (with an acknowledgment) in my set of slides Sincerely, Douglas Wilhelm Harder, MMath dwharder@alumni. uwaterloo. ca 100