Priority Queues Heaps CENG 213 Data Structures Yusuf

  • Slides: 44
Download presentation
Priority Queues (Heaps) CENG 213 Data Structures Yusuf Sahillioğlu 1

Priority Queues (Heaps) CENG 213 Data Structures Yusuf Sahillioğlu 1

Priority Queues • Many applications require that we process records with keys in order,

Priority Queues • Many applications require that we process records with keys in order, but not necessarily in full sorted order. • Often we collect a set of items and process the one with the current minimum value. – e. g. jobs sent to a printer, – Operating system job scheduler in a multi-user environment. – Simulation environments • An appropriate data structure is called a priority queue. 2

Definition • A priority queue is a data structure that supports two basic operations:

Definition • A priority queue is a data structure that supports two basic operations: insert a new item and remove the minimum item. delete. Min insert Priority Queue 3

Simple Implementations • A simple linked list: – Insertion at the front (O(1)); find

Simple Implementations • A simple linked list: – Insertion at the front (O(1)); find minimum (O(N)), or – Keep list sorted; insertion O(N), find. Min O(1) • A binary search tree: – This gives an O(log N) average for both operations. – But BST class supports a lot of operations that are not required. – Self-balancing BSTs O(log N) worst for both operations. • An array: Binary Heap – Does not require links and will support both operations in O(log. N) wost-case time. find. Min in O(1) at worst. 4

Binary Heap • The binary heap is the classic method used to implement priority

Binary Heap • The binary heap is the classic method used to implement priority queues. • We use the term heap to refer to the binary heap. • Heap is different from the term heap used in dynamic memory allocation. • Heap has two properties: – Structure property – Ordering property 5

Structure Property • A heap is a complete binary tree, represented as an array.

Structure Property • A heap is a complete binary tree, represented as an array. • A complete binary tree is a tree that is completely filled, with the possible exception of the bottom level, which is filled from left to right. 6

Properties of a complete binary tree • A complete binary tree of height h

Properties of a complete binary tree • A complete binary tree of height h has between 2 h and 2 h+1 – 1 nodes • The height of a complete binary tree is log N. • It can be implemented as an array such that: – For any element in array position i : • the left child is in position 2 i, • the right child is in the cell after the left child (2 i + 1), and • the parent is in position i/2 . 7

Figure 21. 1 A complete binary tree and its array representation 8

Figure 21. 1 A complete binary tree and its array representation 8

Heap-Order Property • In a heap, for every node X with parent P, the

Heap-Order Property • In a heap, for every node X with parent P, the key in P is smaller than or equal to the key in X. • Thus the minimum element is always at the root. – Thus we get the extra operation find. Min in constant time. • A max heap supports access of the maximum element instead of the minimum, by changing the heap property slightly. 9

Figure 21. 3 Two complete trees: (a) a heap; (b) not a heap 10

Figure 21. 3 Two complete trees: (a) a heap; (b) not a heap 10

Binary Heap Class template <class Comparable> class Binary. Heap { public: Binary. Heap( int

Binary Heap Class template <class Comparable> class Binary. Heap { public: Binary. Heap( int capacity = 100 ); bool is. Empty( ) const; const Comparable & find. Min( ) const; void insert( const Comparable & x ); delete. Min( Comparable & min. Item ); make. Empty( ); private: int the. Size; // Number of elements in heap vector<Comparable> array; // The heap array void build. Heap( ); void percolate. Down( int hole ); }; 11

Basic Heap Operations: Insert • To insert an element X into the heap: –

Basic Heap Operations: Insert • To insert an element X into the heap: – We create a hole in the next available location. – If X can be placed there without violating the heap property, then we do so and are done. – Otherwise • we bubble up the hole toward the root by sliding the element in the hole’s parent down. • We continue this until X can be placed in the hole. • This general strategy is known as a percolate up. 12

Figure 21. 7 Attempt to insert 14, creating the hole and bubbling the hole

Figure 21. 7 Attempt to insert 14, creating the hole and bubbling the hole up 13

Figure 21. 8 The remaining two steps required to insert 14 in the original

Figure 21. 8 The remaining two steps required to insert 14 in the original heap shown in Figure 21. 7 14

Insert procedure // Insert item x into the priority queue, maintaining heap order. //

Insert procedure // Insert item x into the priority queue, maintaining heap order. // Duplicates are allowed. template <class Comparable> void Binary. Heap<Comparable>: : insert( const Comparable & x ) { array[ 0 ] = x; // initialize sentinel if( the. Size + 1 == array. size( ) ) array. resize( array. size( ) * 2 + 1 ); // Percolate up int hole = ++the. Size; for( ; x < array[ hole / 2 ]; hole /= 2 ) array[ hole ] = array[ hole / 2 ]; array[ hole ] = x; } 15

Delete Minimum Ø delete. Min is handled in a similar manner as insertion: •

Delete Minimum Ø delete. Min is handled in a similar manner as insertion: • Remove the minimum; a hole is created at the root. • The last element X must move somewhere in the heap. – If X can be placed in the hole then we are done. – Otherwise, • We slide the smaller of the hole’s children into the hole, thus pushing the hole one level down. • We repeat this until X can be placed in the hole. Ø delete. Min is logarithmic in both the worst and average cases. 16

Figure 21. 10 Creation of the hole at the root 17

Figure 21. 10 Creation of the hole at the root 17

Figure 21. 11 The next two steps in the delete. Min operation 18

Figure 21. 11 The next two steps in the delete. Min operation 18

Figure 21. 12 The last two steps in the delete. Min operation 19

Figure 21. 12 The last two steps in the delete. Min operation 19

delete. Min procedure // Remove the smallest item from the priority queue. // Throw

delete. Min procedure // Remove the smallest item from the priority queue. // Throw Underflow. Exception if empty. template <class Comparable> void Binary. Heap<Comparable>: : delete. Min( ) { if( is. Empty( ) ) throw Underflow. Exception( ); array[ 1 ] = array[ the. Size-- ]; percolate. Down( 1 ); } 20

// Internal method to percolate down in the heap. // hole is the index

// Internal method to percolate down in the heap. // hole is the index at which the percolate begins. template <class Comparable> void Binary. Heap<Comparable>: : percolate. Down( int hole ) { int child; Comparable tmp = array[ hole ]; for( ; hole * 2 <= the. Size; hole = child ) { child = hole * 2; if( child != the. Size && array[child + 1] < array[child]) child++; if( array[ child ] < tmp ) array[ hole ] = array[ child ]; else break; } array[ hole ] = tmp; } 21

Building a Heap • Take as input N items and place them into an

Building a Heap • Take as input N items and place them into an empty heap. • Obviously this can be done with N successive inserts: O(Nlog. N) worst case. • However build. Heap operation can be done in linear time (O(N)) by applying a percolate down routine to nodes in reverse level order. 22

build. Heap method // Establish heap-order property from an arbitrary // arrangement of items.

build. Heap method // Establish heap-order property from an arbitrary // arrangement of items. Runs in linear time. template <class Comparable> void Binary. Heap<Comparable>: : build. Heap( ) { for( int i = the. Size / 2; i > 0; i-- ) percolate. Down( i ); } 23

Figure 21. 17 Implementation of the linear-time build. Heap method Initial complete tree After

Figure 21. 17 Implementation of the linear-time build. Heap method Initial complete tree After percolatedown(7) 24

Figure 21. 18 (a) After percolate. Down(6); (b) after percolate. Down(5) 25

Figure 21. 18 (a) After percolate. Down(6); (b) after percolate. Down(5) 25

Figure 21. 19 (a) After percolate. Down(4); (b) after percolate. Down(3) 26

Figure 21. 19 (a) After percolate. Down(4); (b) after percolate. Down(3) 26

Figure 21. 20 (a) After percolate. Down(2); (b) after percolate. Down(1) and build. Heap

Figure 21. 20 (a) After percolate. Down(2); (b) after percolate. Down(1) and build. Heap terminates 27

Analysis of build. Heap • The linear time bound of build. Heap, can be

Analysis of build. Heap • The linear time bound of build. Heap, can be shown by computing the sum of the heights of all the nodes in the heap, which is the maximum number of dashed lines. • For the perfect binary tree of height h containing N = 2 h+1 – 1 nodes, the sum of the heights of the nodes is N – H – 1. • Thus it is O(N). • Please see this for a cool derivation of O(N) – – http: //www. cs. umd. edu/~meesh/351/mount/lectures/lect 14 -heapsort-analysis-part. pdf Arithmetico-geometric series. 28

Heapsort • The priority queue can be used to sort N items by –

Heapsort • The priority queue can be used to sort N items by – inserting every item into a binary heap and – extracting every item by calling delete. Min N times, thus sorting the result. • An algorithm based on this idea is heapsort. • It is an O(N log. N) worst-case sorting algorithm. 29

Heapsort • The main problem with this algorithm is that it uses an extra

Heapsort • The main problem with this algorithm is that it uses an extra array for the items exiting the heap. • We can avoid this problem as follows: – After each delete. Min, the heap shrinks by 1. – Thus the cell that was last in the heap can be used to store the element that was just deleted. – Using this strategy, after the last delete. Min, the array will contain all elements in decreasing order. • If we want them in increasing order we must use a max heap. 30

Figure 21. 25 Max heap after the build. Heap phase for the input sequence

Figure 21. 25 Max heap after the build. Heap phase for the input sequence 59, 36, 58, 21, 41, 97, 31, 16, 26, 53 31

Figure 21. 26 Heap after the first delete. Max operation 32

Figure 21. 26 Heap after the first delete. Max operation 32

Figure 21. 27 Heap after the second delete. Max operation 33

Figure 21. 27 Heap after the second delete. Max operation 33

Implementation • In the implementation of heapsort, the ADT Binary. Heap is not used.

Implementation • In the implementation of heapsort, the ADT Binary. Heap is not used. – Everything is done in an array. • The root is stored in position 0. • Thus there are some minor changes in the code: – Since we use max heap, the logic of comparisons is changed from > to <. – For a node in position i, the parent is in (i-1)/2, the left child is in 2 i+1 and right child is next to left child. – Percolating down needs the current heap size which is lowered by 1 at every deletion. 34

The heapsort routine /** * Standard heapsort. */ template <class Comparable> void heapsort( vector<Comparable>

The heapsort routine /** * Standard heapsort. */ template <class Comparable> void heapsort( vector<Comparable> & a ) { for( int i = a. size( ) / 2; i >= 0; i-- ) perc. Down( a, i, a. size( ) ); for( int j = a. size( ) - 1; j > 0; j-- ) { swap( a[ 0 ], a[ j ] ); perc. Down( a, 0, j ); } } /* build. Heap */ /* delete. Max */ 35

Analysis of Heapsort • It is an O(N log N) algorithm. – First phase:

Analysis of Heapsort • It is an O(N log N) algorithm. – First phase: Build heap O(N) – Second phase: N delete. Max operations: O(Nlog. N). • Detailed analysis shows that, the average case for heapsort is poorer than quick sort. – Quicksort’s worst case however is far worse. • An average case analysis of heapsort is very complicated, but empirical studies show that there is little difference between the average and worst cases. – Heapsort usually takes about twice as long as quicksort. – Heapsort therefore should be regarded as something of an insurance policy: – On average, it is more costly, but it avoids the possibility of O(N 2). 36

Heap vs. BST 37

Heap vs. BST 37

k largest elements in an array • • • Run outer loop of Bubble

k largest elements in an array • • • Run outer loop of Bubble Sort (ascending) k times Print the last k elements O(nk) for n-size input array Similarly, run outer loop of Selection Sort (descending) k times Print the first k elements O(nk) Similarly, run Quick Sort (descending) Print the first k elements O(nlogn) • Find kth largest in O(n) using order statistic algorithm • Use Quick Sort partition() algo around the kth largest number 38 • O(n)

k largest elements in an array • Build a max heap • Call delete.

k largest elements in an array • Build a max heap • Call delete. Max k times • O(n + klogn) • • • Build a min heap (MH) of the first k elements (A[0. . k-1]) Compare each element after the kth element (A[k. . n-1]) w/ MH. root If element > MH. root, MH. root = element and percolate. Down(1) In the end, MH has k largest elements, e. g. , root is the kth largest O(k + (n-k)logk) 39

Check if given array is min heap 40

Check if given array is min heap 40

Convert max heap to min heap in O(n) • Trick question: same as convert

Convert max heap to min heap in O(n) • Trick question: same as convert normal array to a min heap • Call build. Heap() • O(n) 41

Merge M sorted lists • Naïve solution is to put them all in an

Merge M sorted lists • Naïve solution is to put them all in an array and sort it: O(nlogn) • Cool solution is to use a min heap – Build a min heap (MH) of size M using the first elements of each list – delete. Min from MH and insert next element from same list as deleted elmnt – O(Nlog. M) 42

Stack using a max heap • Assign priorities, i. e. , push time, to

Stack using a max heap • Assign priorities, i. e. , push time, to the elements being pushed. • O(logn) for push and pop. 43

Queue using a min heap • Just use a min heap with the same

Queue using a min heap • Just use a min heap with the same priority, time, as previous slide. • O(logn) for enqueue and dequeue. Queue fro Queue enq Queue deq Queue enq enq deq Queue fro 44