320 likes | 412 Views
DATA STRUCTURES AND ALGORITHMS. 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.
E N D
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 ); }