Mastering AVL Trees: Implementation, Operations, and Rotations
320 likes | 417 Views
Learn about AVL (Adelson-Velskii-Landis) trees, a type of balanced binary search tree. Understand the implementation, operations, and rotations involved in AVL trees. Explore how to maintain balance in AVL trees and handle different insertion cases efficiently.
Mastering AVL Trees: Implementation, Operations, and Rotations
E N D
Presentation Transcript
DATA STRUCTURES ANDALGORITHMS Lecture Notes 6 Prepared by İnanç TAHRALI
ROAD MAP • TREES • Implementation of Trees • Tree Traversals • Binary Trees • The Search Tree ADT-Binary Search Trees • AVL (Adelson-Velskii-Landis) Trees
AVL Trees • AVL tree is a binary search tree with a balance condition • For every node in the tree, height of left and right subtrees can differ at most 1 • Depth of an AVL Tree is O(logN) • Height information is kept in each node structure
AVL Trees • An AVL tree with height 9 • Left subtree is an AVL tree with height 7 • Right subtree is an AVL tree with height 8
AVL Trees • Minimum number of nodes S(h) in an AVL tree of height h is S(h) = S(h-1)+S(h-2)+1 For h=0 S(h)=1 For h=1 S(h)=2 Function S(h) is closed to Fibonacci numbers !
AVL Trees • All tree operations can be performed in O(logN) • except possibly insertion • need to update all balancing information for nodes on the path back to root • Inserting a node can violate AVL tree property • Insert 6 will destroy the balance condition at node 8 • In this case, a rotation must be done
AVL Trees • If node that must be balanced is x, there are 4 cases: 1. insertion into the left subtree of the left child of x 2. insertion into the right subtree of the left child of x 3. insertion into the left subtree of the right child of x 4. insertion into the right subtree of the right child of x • case 1-4 mirror image symetries with respect to x • insertion occurs on the outside and fixed by a single rotation • case 2-3 mirror image symetries with respect to x • insertion occurs on the inside and fixed by a double rotation
Single Rotation for Case 1 • Node k2 violates AVL balance property • its left subtree is to level deeper then right subtree • dashed lines in the middle of the diagram mark the levels
Single Rotation for Case 4 • Similar to single rotation for case 1
Example 1: • AVL property is destroyed by insertion of 6 • Fixed by a single rotation
Example 2: • Start with an initial empty AVL tree • Insert items 3,2,1 and then 4 through 7 in sequential • First problem occurs when inserting item 1 • Perform a single rotation between root and its left child
Example 2: • Inserting 4 is not problem • To insert 5 a single rotation is performed
Example 2: • Next we insert 6 • Causes a balance problem at root
Example 2: • Next we insert 7 • Causes a balance problem
Double Rotation for Case 2 • Single rotation does not work for case 2 and 3 • Subtree Y is too deep and a single rotation does not make it less deep
Double Rotation for Case 2 • Double rotation solves the problem
Example 2: • Continue example 2 with inserting 10 through 16 in reverse order, followed by 8 and 9.
Example 2: • Inserting 16 is easy • Inserting 15causes a height imbalance at node 7 • Right-left double rotation is performed
Example 2: • Inserting 14 requires double rotation
Example 2: • Inserting 13 occurs an imbalance at the root • 13 is not between 4 and 7 so a single rotation will work
Example 2: • Inserting 12 also requires single rotation
Example 2: • To insert 11 and 10 , single rotations need to be performed
Example 2: • Inserting 9 causes the node containing 10 to become unbalanced.
Node declaration for AVL trees template <class Comparable> class AvlTree; template <class Comparable> class AvlNode { Comparable element; AvlNode *left; AvlNode *right; intheight; AvlNode( const Comparable & theElement, AvlNode *lt, AvlNode *rt, int h = 0 ): element( theElement ), left( lt ), right( rt ), height( h ) { } friend class AvlTree<Comparable>; };
Interface of AVL tree template <class Comparable> class AvlTree { public: explicit AvlTree( const Comparable & notFound ); AvlTree( const AvlTree & rhs ); ~AvlTree( ); const Comparable & findMin( ) const; const Comparable & findMax( ) const; const Comparable & find( const Comparable & x ) const; bool isEmpty( ) const; void printTree( ) const; void makeEmpty( ); void insert( const Comparable & x ); void remove( const Comparable & x ); const AvlTree & operator=( const AvlTree & rhs );
private: AvlNode<Comparable> *root; const Comparable ITEM_NOT_FOUND; const Comparable & elementAt( AvlNode<Comparable> *t ) const; void insert( const Comparable & x, AvlNode<Comparable> * & t ) const; AvlNode<Comparable> * findMin( AvlNode<Comparable> *t ) const; AvlNode<Comparable> * findMax( AvlNode<Comparable> *t ) const; AvlNode<Comparable> * find( const Comparable & x, AvlNode<Comparable> *t ) const; void makeEmpty( AvlNode<Comparable> * & t ) const; void printTree( AvlNode<Comparable> *t ) const; AvlNode<Comparable> * clone( AvlNode<Comparable> *t ) const; int height( AvlNode<Comparable> *t ) const; int max( int lhs, int rhs ) const; void rotateWithLeftChild( AvlNode<Comparable> * & k2 ) const; void rotateWithRightChild( AvlNode<Comparable> * & k1 ) const; void doubleWithLeftChild( AvlNode<Comparable> * & k3 ) const; void doubleWithRightChild( AvlNode<Comparable> * & k1 ) const; };
/* Return the height of node t or -1 if NULL. template <class Comparable> int AvlTree<Comparable>::height( AvlNode<Comparable> *t ) const { return t == NULL ? -1 : t->height; }
/* Internal method to insert into a subtree template <class Comparable> void AvlTree<Comparable>::insert( const Comparable & x, AvlNode<Comparable> * & t ) const{ if( t == NULL ) t = new AvlNode<Comparable>( x, NULL, NULL ); else if( x < t->element ){ insert( x, t->left ); if( height( t->left ) - height( t->right ) == 2 ) if( x < t->left->element ) rotateWithLeftChild( t ); else doubleWithLeftChild( t ); } else if( t->element < x ){ insert( x, t->right ); if( height( t->right ) - height( t->left ) == 2 ) if( t->right->element < x ) rotateWithRightChild( t ); else doubleWithRightChild( t ); } else ; t->height = max(height( t->left),height(t->right ) )+1; }
/* routine rotateWithLeftChild template <class Comparable> void AvlTree<Comparable>::rotateWithLeftChild( AvlNode<Comparable> * & k2 ) const { AvlNode<Comparable> *k1 = k2->left; k2->left = k1->right; k1->right = k2; k2->height = max(height(k2->left), height(k2->right) )+1; k1->height = max( height(k1->left), k2->height )+1; k2 = k1; } /* routine rotateWithRightChild template <class Comparable> void AvlTree<Comparable>::rotateWithRightChild( AvlNode<Comparable> * & k1 ) const { AvlNode<Comparable> *k2 = k1->right; k1->right = k2->left; k2->left = k1; k1->height = max(height( k1->left), height( k1->right ) )+1; k2->height = max( height( k2->right ), k1->height ) + 1; k1 = k2; }
/* routine doubleWithLeftChild template <class Comparable> void AvlTree<Comparable>::doubleWithLeftChild( AvlNode<Comparable> * & k3 ) const { rotateWithRightChild( k3->left ); rotateWithLeftChild( k3 ); } /* routine doubleWithRightChild template <class Comparable> void AvlTree<Comparable>::doubleWithRightChild( AvlNode<Comparable> * & k1 ) const { rotateWithLeftChild( k1->right ); rotateWithRightChild( k1 ); }