Heaps,heapsort and priority queue Binhai Zhu Computer Science Department, Montana State University Frequently, presenters must deliver material of a technical nature to an audience unfamiliar with the topic or vocabulary. The material may be complex or heavy with detail. To present technical material effectively, use the following guidelines from Dale Carnegie Training®. Consider the amount of time available and prepare to organize your material. Narrow your topic. Divide your presentation into clear segments. Follow a logical progression. Maintain your focus throughout. Close the presentation with a summary, repetition of the key steps, or a logical conclusion. Keep your audience in mind at all times. For example, be sure data is clear and information is relevant. Keep the level of detail and vocabulary appropriate for the audience. Use visuals to support key points or steps. Keep alert to the needs of your listeners, and you will have a more receptive audience. 11/21/2018
Definition A heap is a binary tree with the following properties: (1) The value of each node is not less than the values stored in each of its children. //heap property (2) The tree is perfectly balanced and leaves in the last level are all in the leftmost positions. 11/21/2018
Example 16 14 10 8 7 9 3 2 4 1 11/21/2018
Example 16 14 10 7 9 3 8 2 4 1 i 1 2 3 4 5 6 7 8 9 10 A[i] 16 14 10 8 7 9 3 2 4 1 11/21/2018
Definition A---array length[A]---number of elements in the array heap-size[A]---number of elements in the heap stored in the array A root of the tree/heap---A[1] Q. Given index i, how do we find its parent/children? i 1 2 3 4 5 6 7 8 9 10 A[i] 16 14 10 8 7 9 3 2 4 1 11/21/2018
Example Q. Given index i, how do we find its parent/children? 16 14 10 3 8 7 9 2 4 1 i 1 2 3 4 5 6 7 8 9 10 A[i] 16 14 10 8 7 9 3 2 4 1 11/21/2018
Example Q. Given index i, how do we find its parent/children? parent(i): 16 14 10 8 7 9 3 2 4 1 i 1 2 3 4 5 6 7 8 9 10 A[i] 16 14 10 8 7 9 3 2 4 1 11/21/2018
Example Q. Given index i, how do we find its parent/children? parent(i): return └ i/2 ┘ 16 14 10 8 7 9 3 2 4 1 i 1 2 3 4 5 6 7 8 9 10 A[i] 16 14 10 8 7 9 3 2 4 1 11/21/2018
Example Q. Given index i, how do we find its parent/children? parent(i): return └ i/2 ┘ 16 left(i): 14 10 8 7 9 3 2 4 1 i 1 2 3 4 5 6 7 8 9 10 A[i] 16 14 10 8 7 9 3 2 4 1 11/21/2018
Example Q. Given index i, how do we find its parent/children? parent(i): return └ i/2 ┘ 16 left(i): return 2i 14 10 8 7 9 3 2 4 1 i 1 2 3 4 5 6 7 8 9 10 A[i] 16 14 10 8 7 9 3 2 4 1 11/21/2018
Example Q. Given index i, how do we find its parent/children? parent(i): return └ i/2 ┘ 16 left(i): return 2i 14 10 right(i): return 2i+1 8 7 9 3 2 4 1 i 1 2 3 4 5 6 7 8 9 10 A[i] 16 14 10 8 7 9 3 2 4 1 11/21/2018
Heap property: 16 14 10 8 7 9 3 2 4 1 i 1 2 3 4 5 6 7 8 9 10 A[i] 16 14 10 8 7 9 3 2 4 1 11/21/2018
Heap property: A[parent(i)]≥A[i] 16 14 10 8 7 9 3 2 4 1 i 1 2 3 4 5 6 7 8 9 10 A[i] 16 14 10 8 7 9 3 2 4 1 11/21/2018
The height of a node is the number of edges on the longest simple downward path from the node to a leaf. The height of a tree is the height of its root. Take-home exercise: An n-element heap has height └ log n ┘. Prove it! 16 14 10 3 8 7 9 2 4 1 11/21/2018
Now we cover a fundamental procedure regarding heaps: the heapify procedure. Condition: binary trees rooted at left(i) and right(i) are heaps, but at A[i] the heap property is violated; i.e., A[i] maybe smaller than its children. 16 4 10 14 7 9 3 2 8 1 11/21/2018
Now we cover a fundamental procedure regarding heaps: the heapify procedure. Condition: binary trees rooted at left(i) and right(i) are heaps, but at A[i] the heap property is violated; i.e., A[i] maybe smaller than its children. 16 X 4 10 14 7 9 3 2 8 1 11/21/2018
X Heapify(A,i) l ← left (i), r ← right(i) If l ≤ heap-size[A] and A[l] > A[i] then largest ← l else largest ← i //find the largest index among A[i],A[left(i)],A[right(i)] If r ≤ heap-size[A] and A[r] > A[largest] then largest ← r If largest ≠ i then exchange A[i] ↔ A[largest] Heapify(A,largest) 16 X 4 10 14 7 9 3 11/21/2018 2 8 1
X Heapify(A,i) l ← left (i), r ← right(i) If l ≤ heap-size[A] and A[l] > A[i] then largest ← l else largest ← i //find the largest index among A[i],A[left(i)],A[right(i)] If r ≤ heap-size[A] and A[r] > A[largest] then largest ← r If largest ≠ i then exchange A[i] ↔ A[largest] Heapify(A,largest) 16 14 10 X 7 9 3 4 11/21/2018 2 8 1
If l ≤ heap-size[A] and A[l] > A[i] then largest ← l Heapify(A,i) l ← left (i), r ← right(i) If l ≤ heap-size[A] and A[l] > A[i] then largest ← l else largest ← i //find the largest index among A[i],A[left(i)],A[right(i)] If r ≤ heap-size[A] and A[r] > A[largest] then largest ← r If largest ≠ i then exchange A[i] ↔ A[largest] Heapify(A,largest) Runnting time: O(log n) 16 14 10 7 9 3 8 11/21/2018 2 1 4
We can use Heapify to convert an unorganized array into a heap. Build-Heap(A) 1.heap-size[A] ← length[A] 2.for i ← └ length[A]/2 ┘ downto 1 3 do Heapify(A,i) 7 i 1 2 3 4 5 6 7 8 9 10 A[i] 4 1 3 2 16 9 10 14 8 7 11/21/2018
Q: Where do we start? 4 1 3 2 16 9 10 14 8 7 i 1 2 3 4 5 6 7 8 9 10 A[i] 4 1 3 2 16 9 10 14 8 7 11/21/2018
Q: Where do we start? i=5 4 i=5 1 3 2 16 9 10 14 8 7 i 1 2 3 4 5 6 7 8 A[i] 4 1 3 2 16 9 10 14 8 7 11/21/2018
i=4 4 1 3 i=4 2 16 9 10 14 8 7 i 1 2 3 4 5 6 7 8 9 10 Old A[i] 4 1 3 2 16 9 10 14 8 7 11/21/2018
i=4, after heapify 4 1 3 i=4 16 9 10 14 2 8 7 i 1 2 3 4 5 6 7 8 9 10 Old A[i] 4 1 3 2 16 9 10 14 8 7 11/21/2018
i=3 4 1 3 i=3 16 9 10 14 2 8 7 i 1 2 3 4 5 6 7 8 9 10 Old A[i] 4 1 3 2 16 9 10 14 8 7 11/21/2018
i=3, after Heapify 4 1 10 i=3 16 9 3 14 2 8 7 i 1 2 3 4 5 6 7 8 9 10 Old A[i] 4 1 3 2 16 9 10 14 8 7 11/21/2018
i=2 4 i=2 1 10 16 9 3 14 2 8 7 i 1 2 3 4 5 6 7 8 9 10 Old A[i] 4 1 3 2 16 9 10 14 8 7 11/21/2018
i=2, run Heapify 4 i=2 16 10 1 9 3 14 2 8 7 i 1 2 3 4 5 6 7 8 9 10 Old A[i] 4 1 3 2 16 9 10 14 8 7 11/21/2018
i=2, after Heapify 4 i=2 16 10 7 9 3 14 2 8 1 i 1 2 3 4 5 6 7 8 9 10 Old A[i] 4 1 3 2 16 9 10 14 8 7 11/21/2018
i=1 i=1 4 16 10 7 9 3 14 2 8 1 i 1 2 3 4 5 6 7 8 9 10 Old A[i] 4 1 3 2 16 9 10 14 8 7 11/21/2018
i=1 i=1, after Heapify 16 14 10 7 9 3 8 2 4 1 i 1 2 3 4 5 6 7 8 9 10 Old A[i] 4 1 3 2 16 9 10 14 8 7 11/21/2018
i=1 i=1, after Heapify 16 14 10 7 9 3 8 2 4 1 i 1 2 3 4 5 6 7 8 9 10 New A[i] 16 14 10 8 7 9 3 2 4 1 11/21/2018
Heapsort(A) Build-Heap(A) for i=length[A] down to 2 exchange A[1] and A[i] heap-size[A]=heap-size[A]-1 Heapify(A,1) 16 14 10 3 8 7 9 4 2 1 11/21/2018
Heapsort(A) Build-Heap(A) for i=length[A] down to 2 exchange A[1] and A[i] heap-size[A]=heap-size[A]-1 Heapify(A,1) 16 14 10 8 7 9 3 4 2 1 11/21/2018 i=10
Heapsort(A) Build-Heap(A) for i=length[A] down to 2 exchange A[1] and A[i] heap-size[A]=heap-size[A]-1 Heapify(A,1) 1 14 10 heap-size=9 8 7 9 3 4 2 16 11/21/2018 i=10
Heapsort(A) Build-Heap(A) for i=length[A] down to 2 exchange A[1] and A[i] heap-size[A]=heap-size[A]-1 Heapify(A,1) After Heapify(A,1) 14 8 10 heap-size=9 4 7 9 3 2 1 16 11/21/2018 i=10
Heapsort(A) Build-Heap(A) for i=length[A] down to 2 exchange A[1] and A[i] heap-size[A]=heap-size[A]-1 Heapify(A,1) 14 8 10 4 7 9 3 2 1 16 11/21/2018 i=9
Heapsort(A) Build-Heap(A) for i=length[A] down to 2 exchange A[1] and A[i] heap-size[A]=heap-size[A]-1 Heapify(A,1) 1 8 10 heap-size=8 4 7 9 3 2 14 16 11/21/2018 i=9
Heapsort(A) Build-Heap(A) for i=length[A] down to 2 exchange A[1] and A[i] heap-size[A]=heap-size[A]-1 Heapify(A,1) After Heapify(A,1) 10 8 9 heap-size=8 7 1 3 4 2 14 16 11/21/2018 i=9
Heapsort(A) Build-Heap(A) for i=length[A] down to 2 exchange A[1] and A[i] heap-size[A]=heap-size[A]-1 Heapify(A,1) 10 8 9 7 1 3 4 2 14 16 11/21/2018 i=8
Heapsort(A) Build-Heap(A) for i=length[A] down to 2 exchange A[1] and A[i] heap-size[A]=heap-size[A]-1 Heapify(A,1) 2 8 9 heap-size=7 7 1 3 4 10 14 16 11/21/2018 i=8
Heapsort(A) Build-Heap(A) for i=length[A] down to 2 exchange A[1] and A[i] heap-size[A]=heap-size[A]-1 Heapify(A,1) After Heapify(A,1) 9 8 3 heap-size=7 7 1 4 2 10 14 16 11/21/2018 i=8
Heapsort(A) Build-Heap(A) for i=length[A] down to 2 exchange A[1] and A[i] heap-size[A]=heap-size[A]-1 Heapify(A,1) After Heapify(A,1) 9 8 3 heap-size=7 7 1 4 2 10 14 16 11/21/2018 i=8
Heapsort(A) Build-Heap(A) for i=length[A] down to 2 exchange A[1] and A[i] heap-size[A]=heap-size[A]-1 Heapify(A,1) 2 i=2 1 3 8 4 7 9 After a few rounds… 10 14 16 11/21/2018
Heapsort(A) Build-Heap(A) for i=length[A] down to 2 exchange A[1] and A[i] heap-size[A]=heap-size[A]-1 Heapify(A,1) After Heapify(A,1) 1 i=2 2 3 heap-size=1 8 9 4 7 10 14 16 11/21/2018
Heapsort(A) Build-Heap(A) for i=length[A] down to 2 exchange A[1] and A[i] heap-size[A]=heap-size[A]-1 Heapify(A,1) 1 2 3 8 9 The array is sorted! 4 7 10 14 16 11/21/2018
Heapsort(A) Build-Heap(A) for i=length[A] down to 2 exchange A[1] and A[i] heap-size[A]=heap-size[A]-1 Heapify(A,1) 1 2 3 8 9 Running time? 4 7 10 14 16 11/21/2018
Heapsort(A) Build-Heap(A) for i=length[A] down to 2 exchange A[1] and A[i] heap-size[A]=heap-size[A]-1 Heapify(A,1) 1 2 3 8 Running time? O(n log n)! 9 4 7 10 14 16 11/21/2018
Priority Queue A priority queue is a data structure for maintaining a set S of elements, each with an associated value called key. //think of scheduling a set of jobs It supports the following operations Insert(S,x) Max(S) Delete-Max(S) //Of course Min is the symmetric case, depending on real application 11/21/2018
Heap-Delete-Max(A) If heap-size[A] < 1 then print “heap underflow” A[1] ← A[heap-size[A]] heap-size[A] ← heap-size[A]-1 Heapify(A,1) return max 11/21/2018
Heap-Delete-Max(A) If heap-size[A] < 1 then print “heap underflow” A[1] ← A[heap-size[A]] heap-size[A] ← heap-size[A]-1 Heapify(A,1) return max Running time? 11/21/2018
Heap-Insert(A,key) heap-size[A] ← heap-size[A] + 1 i ← heap-size[A] While i > 1 and A[parent(i)] < key do A[i] ← A[parent(i)] i ← parent(i) A[i] ← key 11/21/2018
Heap-Insert(A,key) heap-size[A] ← heap-size[A] + 1 i ← heap-size[A] While i > 1 and A[parent(i)] < key do A[i] ← A[parent(i)] i ← parent(i) A[i] ← key 16 14 10 3 8 7 9 2 4 1 15 11/21/2018
Heap-Insert(A,key) heap-size[A] ← heap-size[A] + 1 i ← heap-size[A] While i > 1 and A[parent(i)] < key do A[i] ← A[parent(i)] i ← parent(i) A[i] ← key 16 14 10 3 8 15 9 2 4 1 7 11/21/2018
Heap-Insert(A,key) heap-size[A] ← heap-size[A] + 1 i ← heap-size[A] While i > 1 and A[parent(i)] < key do A[i] ← A[parent(i)] i ← parent(i) A[i] ← key 16 15 10 8 14 9 3 2 4 1 7 Running time? 11/21/2018
Heap-Insert(A,key) heap-size[A] ← heap-size[A] + 1 i ← heap-size[A] While i > 1 and A[parent(i)] < key do A[i] ← A[parent(i)] i ← parent(i) A[i] ← key 16 15 10 8 14 9 3 Question: What if we have to increase the key 15 to 18? 2 4 1 7 11/21/2018