230 likes | 335 Views
DATA STRUCTURES AND ALGORITHMS. Lecture Notes 9 Prepared by İnanç TAHRALI. ROAD MAP. PRIORITY QUEUES (HEAPS) Model Simple Implementations Binary Heap Applications of Priority Queues d-Heaps Leftist Heaps. Review. insert worst case O(logN) average case O(1) deleteMin
E N D
DATA STRUCTURES ANDALGORITHMS Lecture Notes 9 Prepared by İnanç TAHRALI
ROAD MAP • PRIORITY QUEUES (HEAPS) • Model • Simple Implementations • Binary Heap • Applications of Priority Queues • d-Heaps • Leftist Heaps
Review • insert • worst case O(logN) • average case O(1) • deleteMin • worst case O(logN) • average caseO(logN) • buildHeap • worst case O(N) • average case O(N) Running Times of Operations for Binary Heaps • decreaseKey • worst case O(logN) • average case O(1) • increaseKey • worst case O(logN) • average case O(logN) • remove • worst case O(logN) • average case O(logN)
d-Heaps • Nodes have at most d children • Shallow • Insert • one comparison for each percolate • DeleteMin • d-1 comparisons • Good when number of insertions are much greater than deletion
Leftist Heaps • Support merge operation efficiently • Merge O(N) for binary heaps • Using arrays θ(N) • Efficient implementation • Pointers makes others slower • Leftist heap has both a structural property and an ordering property • Its difference from binary heap is that, leftist heaps are not perfectly balanced
Leftist Heaps • Definition : Null path length of a node x is the length of the shortest path from x to a node without two children.
Leftist Heaps • Definition : For each node: NPL of left child is not less than NPL of right child Only left tree is lefist heap
Theorem : A leftist tree with r nodes on the right path must have at least 2r -1 nodes Proof by induction: • if r = 1, there must be at least one tree node. • otherwise, suppose that the theorem is true for 1,2,…,r. • consider a leftist tree with r+1 noes on the right path • then the root has a right subtree with r nodes on the right path, and a left subtree with at least r nodes on the right path (otherwise it would not be leftist) • applying in the inductive hypothesis to these subtrees yields a minimum of 2r -1 nodes in each subtree • this plus the root gives at least 2r+1 -1 nodes in the tree, prooving the theorem. So, r = O(logN)
Leftist Heap Operations • Fundamental operation on leftist heaps is “merging” • What about insert and deleteMin Algorithm if H1 or H2 is NULL return the other one compare the root values (assume H1 is smaller) H1->right = Merge(H1->right, H2) swap the left and right subtrees if necessary if leftist heap property is violated update the NPL of the root of H1 return H1
Leftist Heap Operations Two leftist heaps H1 and H2
Leftist Heap Operations Result of merging H2 and H1’s right subheap
Leftist Heap Operations Result of attaching leftist heap of previous figure as H1’s right child
Leftist Heap Operations Result swapping children of H1’s root
template <class Comparable> class LeftistNode { Comparable element; LeftistNode *left; LeftistNode *right; int npl; LeftistNode(const Comparable & theElement, LeftistNode*lt=NULL, LeftistNode *rt = NULL, int np=0 ) : element( theElement ), left( lt ), right( rt ), npl( np ) { } friend class LeftistHeap<Comparable>; };
template <class Comparable> class LeftistHeap{ public: LeftistHeap( ); LeftistHeap( const LeftistHeap & rhs ); ~LeftistHeap( ); bool isEmpty( ) const; bool isFull( ) const; const Comparable & findMin( ) const; void insert( const Comparable & x ); void deleteMin( ); void deleteMin( Comparable & minItem ); void makeEmpty( ); void merge( LeftistHeap & rhs ); const LeftistHeap & operator=( const LeftistHeap & rhs );
private: LeftistNode<Comparable> *root; LeftistNode<Comparable> * merge( LeftistNode<Comparable>*h1, LeftistNode<Comparable> *h2 ) const; LeftistNode<Comparable> * merge1( LeftistNode<Comparable> *h1, LeftistNode<Comparable> *h2 ) const; void swapChildren( LeftistNode<Comparable> * t ) const; LeftistNode<Comparable> * clone( LeftistNode<Comparable> *t ) const; };
/*Construct the leftist heap. template <class Comparable> LeftistHeap<Comparable>::LeftistHeap( ){ root = NULL; } /* Copy constructor. template <class Comparable> LeftistHeap<Comparable>::LeftistHeap( const LeftistHeap<Comparable> & rhs ) { root = NULL; *this = rhs; } /*Destruct the leftist heap. template <class Comparable> LeftistHeap<Comparable>::~LeftistHeap( ) { makeEmpty( ); }
/*Merge rhs into the priority queue.rhs becomes empty. rhs must be different from this. template <class Comparable> void LeftistHeap<Comparable>::merge( LeftistHeap & rhs ){ if( this == &rhs ) // Avoid aliasing problems return; root = merge( root, rhs.root ); rhs.root = NULL; } /*Internal method to merge two roots. template <class Comparable> LeftistNode<Comparable> * LeftistHeap<Comparable>::merge( LeftistNode<Comparable> *h1,LeftistNode<Comparable> * h2 ) const { if( h1 == NULL ) return h2; if( h2 == NULL )return h1; if( h1->element < h2->element )return merge1( h1, h2 ); elsereturn merge1( h2, h1 ); }
/*Internal method to merge two roots.Assumes trees are not empty, and h1's root contains smallest item. template <class Comparable> LeftistNode<Comparable> *LeftistHeap<Comparable>:: merge1( LeftistNode<Comparable> * h1,LeftistNode<Comparable> * h2 ) const { if( h1->left == NULL ) // Single node h1->left = h2; // Other fields in h1 already accurate else { h1->right = merge( h1->right, h2 ); if( h1->left->npl < h1->right->npl ) swapChildren( h1 ); h1->npl = h1->right->npl + 1; } return h1; }
/*Insert item x into the priority queue, maintaining heap order. template <class Comparable> void LeftistHeap<Comparable>::insert( const Comparable & x ) { root = merge( new LeftistNode<Comparable>( x ), root ); } /*Remove the smallest item from the priority queue. template <class Comparable> void LeftistHeap<Comparable>::deleteMin( ) { if( isEmpty( ) ) throw Underflow( ); LeftistNode<Comparable> *oldRoot = root; root = merge( root->left, root->right ); delete oldRoot; }
Leftist Heap Operations Result of merging right paths of H1 and H2