Heap
Heap
Parent(A, i)
// Input: A: an array representing a heap, i: an array index
// Output: The index in A of the parent of i
// Running Time: O(1)
1 if i == 1 return NULL
2 return bi/2c
Left(A, i)
// Input: A: an array representing a heap, i: an array index
// Output: The index in A of the left child of i
// Running Time: O(1)
1 if 2 i heap-size[A]
2
return 2 i
3 else return NULL
Right(A, i)
// Input: A: an array representing a heap, i: an array index
// Output: The index in A of the right child of i
// Running Time: O(1)
1 if 2 i + 1 heap-size[A]
2
return 2 i + 1
3 else return NULL
Max-Heapify(A, i)
// Input: A: an array where the left and right children of i root heaps (but i may not), i: an array index
// Output: A modified so that i roots a heap
// Running Time: O(log n) where n = heap-size[A] i
1 l Left(i)
2 r Right(i)
3 if l heap-size[A] and A[l] > A[i]
4
largest l
5 else largest i
6 if r heap-size[A] and A[r] < A[largest]
7
largest r
8 if largest 6= i
9
exchange A[i] and A[largest]
10
Max-Heapify(A, largest)
Build-Max-Heap(A)
// Input: A: an (unsorted) array
// Output: A modified to represent a heap.
// Running Time: O(n) where n = length[A]
1 heap-size[A] length[A]
2 for i blength[A]/2c downto 1
3
Max-Heapify(A, i)
1
Heap-Increase-Key(A, i, key)
// Input: A: an array representing a heap, i: an array index, key: a new key greater than A[i]
// Output: A still representing a heap where the key of A[i] was increased to key
// Running Time: O(log n) where n =heap-size[A]
1 if key < A[i]
2
error(New key must be larger than current key)
3 A[i] key
4 while i > 1 and A[Parent(i)] < A[i]
5
exchange A[i] and A[Parent(i)]
6
i Parent(i)
Heap-Sort(A)
// Input: A: an (unsorted) array
// Output: A modified to be sorted from smallest to largest
// Running Time: O(n log n) where n = length[A]
1 Build-Max-Heap(A)
2 for i = length[A] downto 2
3
exchange A[1] and A[i]
4
heap-size[A] heap-size[A] 1
5
Max-Heapify(A, 1)
Heap-Extract-Max(A)
// Input: A: an array representing a heap
// Output: The maximum element of A and A as a heap with this element removed
// Running Time: O(log n) where n =heap-size[A]
1 max A[1]
2 A[1] A[heap-size[A]]
3 heap-size[A] heap-size[A] 1
4 Max-Heapify(A, 1)
5 return max
Max-Heap-Insert(A, key)
// Input: A: an array representing a heap, key: a key to insert
// Output: A modified to include key
// Running Time: O(log n) where n =heap-size[A]
1 heap-size[A] heap-size[A] + 1
2 A[heap-size[A]]
3 Heap-Increase-Key(A[heap-size[A]], key)
Overview
Overview of Heaps
Heap Algorithms (Group Exercise)
More Heap Algorithms!
Master Theorem Review
Heap Overview
For any node, the keys of its children are less than or equal to its key.
We split into three groups and took 5 or 10 minutes to talk. Then each group had to work their example
algorithm on the board.
5 4 9 7 19 8 17 2 6 5 21
21
Build-Max-Heap
17
19
Figure 1: The array to sort and the heap you should find.
Group 2: Heap-Increase-Key
For the heap shown in Figure 2 (which Group 1 will build), show what happens when you use HeapIncrease-Key to increase key 2 to 22. Make sure you argue why what youre doing is O(log n). (Hint:
Argue about how much work you do at each level)
21
17
19
Group 3: Heap-Sort
Given the heap shown in Figure 3 (which Groups 1 and 2 will build for you), show how you use it to
sort. You do not need to explain the Max-Heapify or the Build-Max-Heap routine, but you should
make sure you explain why the runtime of this algorithm is O(n log n). Remember the running time of
Max-Heapify is O(log n).
22
17
21
19
Note Heap-Extract-Max and Max-Heap-Insert procedures since we didnt discuss them in class:
Heap-Extract-Max(A)
1 max A[1]
2 A[1] A[heap-size[A]]
3 heap-size[A] heap-size[A] 1
4 Max-Heapify(A, 1)
5 return max
Max-Heap-Insert(A, key)
1 heap-size[A] heap-size[A] + 1
2 A[heap-size[A]]
3 Heap-Increase-Key(A[heap-size[A]], key)
Trivial Analysis: Each call to Max-Heapify requires log(n) time, we make n such calls O(n log n).
Tighter Bound: Each call to Max-Heapify requires time O(h) where h is the height of node i.
Therefore running time is
!
log
log
Xn h
Xn
n
O(h)
= O n
| {z }
2h + 1
2h
| {z }
h=0
h=0
Running time for each node
Number of nodes at height h
!
X
h
= O n
2h
h=0
O(n)
Note
h=0
(1)
h/2h = 2.
(We didnt get to this in this weeks recitation, maybe next time).
Loop Invariant: Each time through the for loop, each node greater than i is the root of a max-heap.
Initialization: At the first iteration, each node larger than i is at the root of a heap of size 1, which
is trivially a heap.
Maintainance: Since the children of i are larger than i, by our loop invariant, the children of i are
roots of max-heaps. Therefore, the requirement for Max-Heapify is satisfied and, at the end of the
loop, index i also roots a heap. Since we decrement i by 1 each time, the invariant holds.
Termination:
a max-heap.
Discussion:
What is the loop invariant for Heap-Sort? (All keys greater than i are sorted).
Initialization:
Trivial.
Maintainance: We always remove the largest value from the heap. We can call Max-Heapify because
we have shrunk the size of the heap so that the roots children are roots of good heaps (although the
root is not the root of a good heap).
Termination:
i=0
Traverse-Tree(T )
1 if left-child(root[T ]) == NULL and right-child(root[T ]) == NULL return
2 output left-child(root[T ]), right-child(root[T ])
3 Traverse-Tree(right-child(root[T ]))
4 Traverse-Tree(left-child(root[T ]))
Recurrence is T = 2T (n/2) + O(1). a = 2, b = 2, nlogb (a) = n, f (n) = 1. Master Theorem Case 1,
Running Time O(1).
Multiply(x, y)
1 n max(|x|, |y|) // |x| is size of x in bits
2 if n = 1 return xy
3 xL x[1 : n/2], xR x[n/2 + 1 : n], yL y[1 : n/2], yR y[n/2 + 1 : n]
4 P1 = Multiply(xL , yL )
5 P2 = Multiply(xR , yR )
6 P3 = Multiply(xL + xR , yL + yR )
7 return 2n P1 + 2n/2 (P3 P1 P2 ) + P2
Recurrence Relation: T (n) = 3T (n/2) + O(n) (Note: Addition takes linear time in number of bits).
a = 3, b = 2, nlogb (a) = nlog3 (2) , f (n) = O(n), Case 1 of Master Theorem, O(nlog3 (2) )
MatrixMultiply(X, Y )
1 n sizeof (X) // Assume X and Y are the same size and square
2 if n = 1, return XY
3 // Split X and Y into four quadrants:
A U pperLef t(X), B U pperRight(X), C LowerLef t(X), D LowerRight(X)
E U pperLef t(Y ), F U pperRight(Y ), G LowerLef t(Y ), H LowerRight(Y )
4 U L MatrixMultiply(A, E) + MatrixMultiply(B, G)
5 U R MatrixMultiply(A, F ) + MatrixMultiply(B, H)
6 LL MatrixMultiply(C, E) + MatrixMultiply(D, G)
7 LR MatrixMultiply(C, F ) + MatrixMultiply(D, H)
8 return matrix with U L as upper left quadrant, U R as upper right, LL as lower left, LR as lower right.
Recurrence Relation: T (n) = 8T (n/2) + O(n2 ). a = 8, b = 2, nlogb (a) = n3 , f (n) = n2 . Case 1 of the
Master Theorem, O(n3 ).