Heaps heapsort and priority queue Binhai Zhu Computer
Heaps, heapsort and priority queue Binhai Zhu Computer Science Department, Montana State University 11/29/2020 1
Definition l 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/29/2020 2
Example 16 14 10 7 8 2 4 9 3 1 11/29/2020 3
Example 16 14 10 7 8 2 3 9 1 4 i 1 2 3 4 5 6 A[i] 16 14 10 8 7 9 7 3 8 9 10 2 4 1 11/29/2020 4
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 A[i] 16 14 10 8 7 9 7 3 8 9 10 2 4 1 11/29/2020 5
Q. Given index i, how do we find its parent/children? Example 16 14 10 7 8 2 3 9 1 4 i 1 2 3 4 5 6 A[i] 16 14 10 8 7 9 7 3 8 9 10 2 4 1 11/29/2020 6
Q. Given index i, how do we find its parent/children? Example parent(i): 16 14 10 7 8 2 3 9 1 4 i 1 2 3 4 5 6 A[i] 16 14 10 8 7 9 7 3 8 9 10 2 4 1 11/29/2020 7
Q. Given index i, how do we find its parent/children? Example parent(i): return └ i/2 ┘ 16 14 10 7 8 2 3 9 1 4 i 1 2 3 4 5 6 A[i] 16 14 10 8 7 9 7 3 8 9 10 2 4 1 11/29/2020 8
Q. Given index i, how do we find its parent/children? Example parent(i): return └ i/2 ┘ 16 left(i): 14 10 7 8 2 3 9 1 4 i 1 2 3 4 5 6 A[i] 16 14 10 8 7 9 7 3 8 9 10 2 4 1 11/29/2020 9
Q. Given index i, how do we find its parent/children? Example parent(i): return └ i/2 ┘ 16 left(i): return 2 i 14 10 7 8 2 3 9 1 4 i 1 2 3 4 5 6 A[i] 16 14 10 8 7 9 7 3 8 9 10 2 4 1 11/29/2020 10
Q. Given index i, how do we find its parent/children? Example parent(i): return └ i/2 ┘ 16 left(i): return 2 i 14 10 7 8 2 right(i): return 2 i+1 3 9 1 4 i 1 2 3 4 5 6 A[i] 16 14 10 8 7 9 7 3 8 9 10 2 4 1 11/29/2020 11
Heap property: 16 14 10 7 8 2 3 9 1 4 i 1 2 3 4 5 6 A[i] 16 14 10 8 7 9 7 3 8 9 10 2 4 1 11/29/2020 12
Heap property: A[parent(i)]≥A[i] 16 14 10 7 8 2 3 9 1 4 i 1 2 3 4 5 6 A[i] 16 14 10 8 7 9 7 3 8 9 10 2 4 1 11/29/2020 13
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 7 8 2 4 1 9 3 11/29/2020 14
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 7 14 2 8 1 9 3 11/29/2020 15
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 7 14 2 8 1 9 3 11/29/2020 16
Heapify(A, i) 1. l ← left (i), r ← right(i) 2. If l ≤ heap-size[A] and A[l] > A[i] 3. then largest ← l 4. else largest ← i //find the largest index among A[i], A[left(i)], A[right(i)] 5. If r ≤ heap-size[A] and A[r] > A[largest] 6. then largest ← r 16 7. If largest ≠ i 8. 9. then exchange A[i] ↔ A[largest] X Heapify(A, largest) 4 10 7 14 2 8 1 9 3 11/29/2020 17
Heapify(A, i) 1. l ← left (i), r ← right(i) 2. If l ≤ heap-size[A] and A[l] > A[i] 3. then largest ← l 4. else largest ← i //find the largest index among A[i], A[left(i)], A[right(i)] 5. If r ≤ heap-size[A] and A[r] > A[largest] 6. then largest ← r 7. If largest ≠ i 8. 9. 16 then exchange A[i] ↔ A[largest] Heapify(A, largest) 14 X 2 10 7 4 8 1 9 3 11/29/2020 18
Heapify(A, i) 1. l ← left (i), r ← right(i) 2. If l ≤ heap-size[A] and A[l] > A[i] 3. then largest ← l 4. else largest ← i //find the largest index among A[i], A[left(i)], A[right(i)] 5. If r ≤ heap-size[A] and A[r] > A[largest] 6. then largest ← r 7. If largest ≠ i 8. 9. 16 then exchange A[i] ↔ A[largest] Heapify(A, largest) 14 10 7 8 10. Runnting time: O(log n) 2 4 1 9 3 11/29/2020 19
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 A[i] 1 4 2 3 4 5 6 7 8 9 10 1 3 2 16 9 10 14 8 7 11/29/2020 20
Q: Where do we start? 4 1 3 16 2 14 8 9 10 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/29/2020 21
Q: Where do we start? i=5 4 1 3 i=5 16 2 14 8 9 10 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/29/2020 22
i=4 4 1 3 i=4 2 14 i 16 8 9 10 7 1 2 3 4 5 6 7 8 9 10 Old A[i] 4 1 3 2 16 9 10 14 8 7 11/29/2020 23
i=4, after heapify 4 1 i=4 16 14 2 i 3 8 9 10 7 1 2 3 4 5 6 7 8 9 10 Old A[i] 4 1 3 2 16 9 10 14 8 7 11/29/2020 24
i=3 4 1 3 16 14 2 i Old A[i] 8 i=3 9 10 7 1 2 3 4 5 6 7 8 9 10 4 1 3 2 16 9 10 14 8 7 11/29/2020 25
i=3, after Heapify 4 1 10 16 14 2 i Old A[i] 8 i=3 3 9 7 1 2 3 4 5 6 7 8 9 10 4 1 3 2 16 9 10 14 8 7 11/29/2020 26
i=2 4 i=2 1 10 16 14 2 i 8 3 9 7 1 2 3 4 5 6 7 8 9 10 Old A[i] 4 1 3 2 16 9 10 14 8 7 11/29/2020 27
i=2, run Heapify 4 i=2 16 10 1 14 2 i 8 3 9 7 1 2 3 4 5 6 7 8 9 10 Old A[i] 4 1 3 2 16 9 10 14 8 7 11/29/2020 28
i=2, after Heapify 4 i=2 16 10 7 14 2 i 8 3 9 1 1 2 3 4 5 6 7 8 9 10 Old A[i] 4 1 3 2 16 9 10 14 8 7 11/29/2020 29
i=1 4 16 10 7 14 2 i 8 3 9 1 1 2 3 4 5 6 7 8 9 10 Old A[i] 4 1 3 2 16 9 10 14 8 7 11/29/2020 30
i=1 i=1, after Heapify 16 14 10 7 8 2 i 3 9 1 4 1 2 3 4 5 6 7 8 9 10 Old A[i] 4 1 3 2 16 9 10 14 8 7 11/29/2020 31
i=1 i=1, after Heapify 16 14 10 7 8 2 i New A[i] 3 9 1 4 1 2 3 4 5 6 16 14 10 8 7 9 7 3 8 9 10 2 4 1 11/29/2020 32
Heapsort(A) 1. Build-Heap(A) 2. for i=length[A] down to 2 3. exchange A[1] and A[i] 4. heap-size[A]=heap-size[A]-1 5. Heapify(A, 1) 16 14 10 7 8 2 4 1 9 3 11/29/2020 33
Heapsort(A) 1. Build-Heap(A) 2. for i=length[A] down to 2 3. exchange A[1] and A[i] 4. heap-size[A]=heap-size[A]-1 5. Heapify(A, 1) 16 14 10 7 8 2 4 1 9 i=10 3 11/29/2020 34
Heapsort(A) 1. Build-Heap(A) 2. for i=length[A] down to 2 3. exchange A[1] and A[i] 4. heap-size[A]=heap-size[A]-1 5. Heapify(A, 1) 1 14 10 heap-size=9 7 8 2 4 16 9 i=10 3 11/29/2020 35
Heapsort(A) 1. Build-Heap(A) 2. for i=length[A] down to 2 3. exchange A[1] and A[i] 4. heap-size[A]=heap-size[A]-1 5. Heapify(A, 1) After Heapify(A, 1) 14 8 10 heap-size=9 7 4 2 1 16 9 i=10 3 11/29/2020 36
Heapsort(A) 1. Build-Heap(A) 2. for i=length[A] down to 2 3. exchange A[1] and A[i] 4. heap-size[A]=heap-size[A]-1 5. Heapify(A, 1) 14 8 10 7 4 2 1 i=9 16 9 3 11/29/2020 37
Heapsort(A) 1. Build-Heap(A) 2. for i=length[A] down to 2 3. exchange A[1] and A[i] 4. heap-size[A]=heap-size[A]-1 5. Heapify(A, 1) 1 8 10 heap-size=8 7 4 2 14 i=9 16 9 3 11/29/2020 38
Heapsort(A) 1. Build-Heap(A) 2. for i=length[A] down to 2 3. exchange A[1] and A[i] 4. heap-size[A]=heap-size[A]-1 5. Heapify(A, 1) After Heapify(A, 1) 10 9 8 heap-size=8 7 4 2 14 i=9 16 1 3 11/29/2020 39
Heapsort(A) 1. Build-Heap(A) 2. for i=length[A] down to 2 3. exchange A[1] and A[i] 4. heap-size[A]=heap-size[A]-1 5. Heapify(A, 1) 10 9 8 7 4 2 i=8 14 16 1 3 11/29/2020 40
Heapsort(A) 1. Build-Heap(A) 2. for i=length[A] down to 2 3. exchange A[1] and A[i] 4. heap-size[A]=heap-size[A]-1 5. Heapify(A, 1) 2 9 8 heap-size=7 7 4 10 i=8 14 16 1 3 11/29/2020 41
Heapsort(A) 1. Build-Heap(A) 2. for i=length[A] down to 2 3. exchange A[1] and A[i] 4. heap-size[A]=heap-size[A]-1 5. Heapify(A, 1) After Heapify(A, 1) 9 8 3 heap-size=7 7 4 10 i=8 14 16 1 2 11/29/2020 42
Heapsort(A) 1. Build-Heap(A) 2. for i=length[A] down to 2 3. exchange A[1] and A[i] 4. heap-size[A]=heap-size[A]-1 5. Heapify(A, 1) After Heapify(A, 1) 9 8 3 heap-size=7 7 4 10 i=8 14 16 1 2 11/29/2020 43
Heapsort(A) 1. Build-Heap(A) 2. for i=length[A] down to 2 3. exchange A[1] and A[i] 4. heap-size[A]=heap-size[A]-1 5. Heapify(A, 1) 2 i=2 1 3 7 4 After a few rounds… 10 14 16 8 9 11/29/2020 44
Heapsort(A) 1. Build-Heap(A) 2. for i=length[A] down to 2 3. exchange A[1] and A[i] 4. heap-size[A]=heap-size[A]-1 5. Heapify(A, 1) After Heapify(A, 1) 1 i=2 2 3 heap-size=1 7 4 10 14 16 8 9 11/29/2020 45
Heapsort(A) 1. Build-Heap(A) 2. for i=length[A] down to 2 3. exchange A[1] and A[i] 4. heap-size[A]=heap-size[A]-1 5. Heapify(A, 1) 1 2 The array is sorted! 10 3 7 4 14 16 8 9 11/29/2020 46
Heapsort(A) 1. Build-Heap(A) 2. for i=length[A] down to 2 3. exchange A[1] and A[i] 4. heap-size[A]=heap-size[A]-1 5. Heapify(A, 1) 1 2 3 7 4 Running time? 10 14 16 8 9 11/29/2020 47
Heapsort(A) 1. for i=length[A] down to 2 2. Build-Heap(A) 3. exchange A[1] and A[i] 4. heap-size[A]=heap-size[A]-1 5. Heapify(A, 1) 1 2 Running time? O(n log n)! 10 3 7 4 14 16 8 9 11/29/2020 48
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/29/2020 49
Heap-Delete-Max(A) 1. 2. If heap-size[A] < 1 then print “heap underflow” 3. max ← A[1] 4. A[1] ← A[heap-size[A]] 5. heap-size[A] ← heap-size[A]-1 6. Heapify(A, 1) 7. return max 11/29/2020 50
Heap-Delete-Max(A) 1. 2. If heap-size[A] < 1 then print “heap underflow” 3. max ← A[1] 4. A[1] ← A[heap-size[A]] 5. heap-size[A] ← heap-size[A]-1 6. Heapify(A, 1) 7. return max Running time? 11/29/2020 51
Heap-Insert(A, key) 1. heap-size[A] ← heap-size[A] + 1 2. i ← heap-size[A] 3. While i > 1 and A[parent(i)] < key 4. 5. 6. do A[i] ← A[parent(i)] i ← parent(i) A[i] ← key 11/29/2020 52
Heap-Insert(A, key) 1. heap-size[A] ← heap-size[A] + 1 2. i ← heap-size[A] 3. While i > 1 and A[parent(i)] < key 4. 5. 6. do A[i] ← A[parent(i)] 16 i ← parent(i) A[i] ← key 14 10 7 8 2 4 1 9 15 3 11/29/2020 53
Heap-Insert(A, key) 1. heap-size[A] ← heap-size[A] + 1 2. i ← heap-size[A] 3. While i > 1 and A[parent(i)] < key 4. 5. 6. do A[i] ← A[parent(i)] 16 i ← parent(i) A[i] ← key 14 10 15 8 2 4 1 9 7 3 11/29/2020 54
Heap-Insert(A, key) 1. heap-size[A] ← heap-size[A] + 1 2. i ← heap-size[A] 3. While i > 1 and A[parent(i)] < key 4. 5. 6. do A[i] ← A[parent(i)] 16 i ← parent(i) A[i] ← key 15 10 14 8 Running time? 2 4 1 9 7 3 11/29/2020 55
Heap-Insert(A, key) 1. heap-size[A] ← heap-size[A] + 1 2. i ← heap-size[A] 3. While i > 1 and A[parent(i)] < key 4. 5. 6. do A[i] ← A[parent(i)] 16 i ← parent(i) A[i] ← key 15 10 14 8 Question: What if we have to increase the key 15 to 18? 2 4 1 9 7 3 11/29/2020 56
- Slides: 56