This document discusses heapsort and priority queues implemented using binary heaps. Heapsort uses a max heap to sort an array in O(n log n) time by repeatedly extracting the maximum element and placing it in its sorted position. A priority queue uses a min heap to retrieve the minimum element in O(log n) time for insertions and deletions by keeping the minimum key at the root.
1. Topics
Heap
Heapsort
Implementation
Priority Queue
Implementation
HeapSort
(This tutorials uses maxheap and sorting in ascending order. Similarly alternative
approach is possible)
Heap sort is a comparison based sorting technique based on Binary Heap data
structure. It is similar to selection sort where we first find the maximum element and
place the maximum element at the end. We repeat the same process for remaining
element.
Heap Sort Algorithm for sorting in increasing order:
1. Build a max heap from the input data.
2. At this point, the largest item is stored at the root of the heap. Replace it with
the last item of the heap followed by reducing the size of heap by 1. Finally,
heapify the root of tree.
3. Repeat above steps while size of heap is greater than 1.
How to build the heap?
Heapify procedure can be applied to a node only if its children nodes are heapified.
So the heapification must be performed in the bottom up order.
Lets understand with the help of an example:
Input data: 4, 10, 3, 5, 1
4(0)
/
10(1) 3(2)
/
5(3) 1(4)
The numbers in bracket represent the indices in the array
representation of data.
2. Applying heapify procedure to index 1:
4(0)
/
10(1) 3(2)
/
5(3) 1(4)
Applying heapify procedure to index 0:
10(0)
/
5(1) 3(2)
/
4(3) 1(4)
The heapify procedure calls itself recursively to build heap
in top down manner.
Implementation:
1. // C++ program for implementation of Heap Sort
2. #include <iostream>
3.
4. using namespace std;
5.
6. // To heapify a subtree rooted with node i which is
7. // an index in arr[]. n is size of heap
8. void heapify(int arr[], int n, int i)
9. {
10. int largest = i; // Initialize largest as root
11. int l = 2*i + 1; // left = 2*i + 1
12. int r = 2*i + 2; // right = 2*i + 2
13.
14. // If left child is larger than root
15. if (l < n && arr[l] > arr[largest])
16. largest = l;
17.
18. // If right child is larger than largest so far
19. if (r < n && arr[r] > arr[largest])
20. largest = r;
21.
22. // If largest is not root
23. if (largest != i)
24. {
25. swap(arr[i], arr[largest]);
26.
27. // Recursively heapify the affected sub-tree
28. heapify(arr, n, largest);
29. }
30. }
31.
3. 32. // main function to do heap sort
33. void heapSort(int arr[], int n)
34. {
35. // Build heap (rearrange array)
36. for (int i = n / 2 - 1; i >= 0; i--)
37. heapify(arr, n, i);
38.
39. // One by one extract an element from heap
40. for (int i=n-1; i>0; i--)
41. {
42. // Move current root to end
43. swap(arr[0], arr[i]);
44.
45. // call max heapify on the reduced heap
46. heapify(arr, i, 0);
47. }
48. }
49.
50. /* A utility function to print array of size n */
51. void printArray(int arr[], int n)
52. {
53. for (int i=0; i<n; ++i)
54. cout << arr[i] << " ";
55. cout << "n";
56. }
57.
58. // Driver program
59. int main()
60. {
61. int arr[] = {12, 11, 13, 5, 6, 7};
62. int n = sizeof(arr)/sizeof(arr[0]);
63.
64. heapSort(arr, n);
65.
66. cout << "Sorted array is n";
67. printArray(arr, n);
68. }
Output:
Sorted array is
5 6 7 11 12 13
4. Priority Queue
Priority queues are useful for any application that involves processing elements
based on some priority. Previously we used array and linked list to implement
priority queue which has worst case insertion complexity- O(N). We can use heaps
to implement the priority queue. It will take O(log N) time to insert in the priority
queue. Based on heap structure, priority queue also has two types: max- priority
queue and min - priority queue.
Let’s focus on min-priority Queue. Using a min-heap to implement a min-priority
queue, we will always have the element of highest priority (smallest key) at the root
node of the heap.
The heap has to support four major operations insert(key), extractMin(),
deleteMin() and decreaseKey(index,newKey).
The reason we re-implement a priority queue is to improve its efficiency. When we
implemented a priority queue with an array or a linked list, the efficiency of some
operations were O(n).
insert deleteMin extractMin
ordered array O(n) O(1) O(1)
ordered list O(n) O(1) O(1)
unordered array O(1) O(n) O(n)
unordered list O(1) O(n) O(n)
Using a binary heap, the runtime of both the deleteMin and insert operations is
O(log n).
insert deleteMin extractMin
binary heap O(log n) O(log n) O(1)
Implementation:
(Same as the previous class.)