Heapsort Sorting in place Only a constant number of elements are stored outside the input array at any time. insertion sort mergesort heapsort O(n log n) No Yes Yes sorting in place Yes No Yes
Heap Structure A binary tree of height h 21 18 9 11 5 3 6 2 14 10 7 8 complete at least through depth h – 1 possibly missing some rightmost leaves at depth h Example 21 18 9 11 5 3 6 2 14 10 7 8
Array Storage of a Heap 21 18 14 9 11 10 8 5 3 6 2 7 Index 1 2 3 4 5 6 7 8 9 10 11 12 Easy access of neighboring nodes: i/2-th node parent(i) = i/2 i-th node left(i) = 2i right(i) = 2i + 1 2i-th node (2i+1)-st node
Height of a Heap A heap of n nodes with height h Complete up to depth h – 1 1 + 2 + … + 2 = 2 – 1 < n h h–1 Possibly missing nodes at depth h 1 + 2 + … + 2 = 2 – 1 n h+1 h Combining them: 2 n < 2 h h+1 h lg n < h + 1 h = lg n
Heap Property for max-heap A[parent(i)] A[i], i > 1 21 18 9 11 5 3 6 2 14 10 7 8 for min-heap A[parent(i)] A[i], i > 1
Maintaining Heap Property Assume Subtrees rooted at left(i) and right (i) are heaps. Subtree rooted at i may not be a heap. Recursive procedure Heapify(A, i) Example Heapify(A, 3) i = 3 21 18 9 11 5 3 6 2 7 14 10 8 21 18 9 11 5 3 6 2 14 7 10 8 14 > 8 > 7 i = 6
Heapify 21 18 9 11 5 3 6 2 14 10 7 8 Heapify(A, 3) Heapify(A, 6) Step 1 Fix the heap property among A[i], A[left(i)], A[right(i)]. // (1) Step 2 Heapify(A, 2i) or Heapify(A, 2i+1). // T(2n/3) Let T(n) be the running time.
Upper Bound on Subtree Size Claim 1 Each subtree has size < 2n/3 Proof Most unbalanced heap of height h is #nodes 1 2 h – 1 height h #nodes left subtree right subtree tree 1 + 2 – 1 + 2 – 1 h h–1 = 2 + 2 – 1 = n 1 + … + 2 = 2 – 1 h h–1 1 + … + 2 = 2 – 1 h–1 h–2 Each subtree has size 2 – 1 2 + 2 – 1 h–1 h n < 2n / 3
Running Time of Heapify We now have T(n) T(2n/3) + O(1) Running time : T(n) = O(lg n) not ‘=‘! Why O not ?
Building a Heap Build-Heap(A) for i n / 2 downto 1 do Heapify(A, i) 18 2 5 6 9 3 21 11 7 10 14 8 18 2 5 6 9 3 21 11 7 14 10 8 Heapify(A, 6)
Example (cont’d) 18 2 5 21 9 3 6 11 7 14 10 8 Heapify(A, 5) 18 2 9 21 5 3 6 11 7 14 10 8 Heapify(A, 4) Heapify(A, 3) 18 2 9 21 5 3 6 11 14 7 10 8 18 2 9 21 5 3 6 11 14 10 7 8 Heapify(A, 6) // recursive Heapify(A, 2)
Example (cont’d) 18 21 9 2 5 3 6 11 14 10 7 8 18 21 9 11 5 3 6 2 14 10 7 8 Heapify(A, 5) // recursive Heapify(A, 1) 21 18 9 11 5 3 6 2 14 10 7 8
Analysis 1 O(n lg n) -- not asymptotically tight! Build-Heap(A) for i length(A) / 2 downto 1 // n/2 iterations do Heapify(A, i) // O(lg n) each call O(n lg n) -- not asymptotically tight! Observations each call indeed takes O(h) h is small for most nodes.
Analysis 2 Claim 2 There are at most n / 2 nodes with height h. (Ex. 6.3-3) Running time n/2 O(h) = O ( n h / 2 ) h+1 h = 0 lg n h = 1 S = O(n) 2S – S = h / 2 – h / 2 h = 1 lg n h+1 h Or use k x with x = 1/2 k = 1/2 + (h+1) / 2 – h / 2 h = 1 lg n –1 h+1 lg n = 1/2 + 1 / 2 – lg n / 2 < 1 lg n –1 h = 1 h+1 lg n +1 Theorem Build-Heap runs in O(n) time.
Analysis 3 p(v): the path from node v to its left child and then following the right child pointers to a leaf 18 2 5 6 9 3 21 11 7 10 14 8 p(18) p(7) p(10) p(5) p(6) p(2)
Properties of p-Paths a b c g d e f i p-paths are edge-disjoint; i.e., p(u) and p(v) does not share a common edge whenever u v. every edge not on the rightmost path lies on some p-path. n – 1 edges in the heap. lg n or lg n – 1 edges on the rightmost path. height n – lg n p-path edges.
More Properties either node height h(v) = | p(v)| or h(v) = |p(v)| +1. h(v) = |p(v)| +1 if and only if h(v) > 1 and the left subtree of v is not complete. v incomplete For example, h(a) = 3 but p(a) has two edges on the previous slide. lg n – 1 nodes with h(v) = |p(v)| +1 (according to the heap structure). h(v) n – lg n + lg n – 1 = n – 1 v
The Heapsort Algorithm Build-Heap(A) // O(n) for i length(A) downto 2 do exchange A[1] A[i] heap-size[A] heap-size[A] – 1 heapify(A, 1) // O(lg n) 21 18 9 11 5 3 6 2 14 10 7 8 6 7 18 9 11 5 3 2 14 10 21 8
Heapsort Example 9 18 11 7 5 3 6 2 14 10 21 8 10 2 11 9 7 5 3 6 18 14 21 8 14 11 9 7 5 3 6 18 10 2 21 8 11 9 6 7 5 3 14 18 10 2 21 8
Heapsort Example 10 9 6 7 5 11 14 18 8 2 21 3 9 7 6 5 10 11 14 18 8 2 21 3 8 7 6 5 10 11 14 18 3 2 21 9 7 6 2 5 10 11 14 18 3 8 21 9
Example (cont’d) 9 6 5 2 7 10 11 14 18 3 8 21 5 2 6 7 10 11 14 18 3 8 21 9 3 2 6 7 10 11 14 18 5 8 21 9 2 3 6 7 10 11 14 18 5 8 21 9 2, 3, 5, 6, 7, 8, 9, 10, 11, 14, 18, 21
Priority Queue One of the most popular applications of a heap. A priority queue maintains a set S of items, each with a key, and supports these operations: Maximum (S) // O(1) Extract-Max(S) // O(lg n) Increase-Key(S, x, k) // increase the value of x’s key to k; moving // x up repeatedly if necessary.O(lg n) Insert(S, x) // O(lg n) Applications in job scheduling (e.g., processes in OS) event-driven simulator