A heap is a binary tree that satisfies these special SHAPE
and ORDER properties:
- Its shape must be a complete
binary tree.
- For each node in the heap, the value stored in that node
is greater than or equal to the value in each of its children.
|
Which are Heaps?
(no)
(yes)
|
Use of Heaps
- heaps have special properties that can make certain kinds
of operations on stored data more efficient
- Question: where is the largest element in a heap always stored?
|
Node Ordering in a Heap (for array implementation)
do by ordering across levels starting at the top |
|
Can now store elements using this ordering |
|
Some Notes:
- Parent of node i is stored at array location: floor(i/2)
- Left child of node i is stored at array location: 2i
- Right child of node i is stored at array location: 2i
+ 1
|
Heap Operations
- Heapify Operation that insures
that a heap stays a heap
- Build-heap Converts an unordered
array into a heap.
- Heapsort Using the array
storing the heap sorts the array in place.
|
Heapify
This procedure is used by the heapsort. It assumes that the values
in the array are almost a heap. It is only
the root that may be violating the heap principle (the
left and right child of the root are assumed to be heaps).
Used to insert new element in the heap
//pseudo-code
Heapify(int A[], int current)
{ if left(current) <= A.heapsize() and A[left(current)] > A[current]
largest = left(current)
else
largest = current
if right(current) <= A.heapsize() and A[right(current)] > A[largest]
largest = right(current)
if largest != current
swap(A[largest], A[current]
Heapify(A, largest)
}
int left(int index)
return 2 * index
int right(int index)
return 2 * index + 1
int parent(int index)
return index / 2
Running Time of Heapify
What is the running time of Heapify?
Heapify is recursive so we will create a
recurrence relation to express the running time:
The running time of the algorithm without the
recursive call is constant, O(1).
How big is the subtree that is heapified?
The largest possible subtree (when the last row
is half full) is 2/3 the size of n so
the recursive call will take T(2n/3) time so the
recurrence is
T(n) <= T(2n/3) + O(1)
Using the master theorem, f(n) = 1, a = 1, b = 2/3
so we use case 2 since
so heapify is O(lgn) |
Building -Heap
Running Time of Heapify
- The for loop is run n/2 times.
- And we know that Heapify has running time O(lgn).
- So the running time of Build-Heap is O(nlgn) (note
that the depth of the run on each Heapify is many times constant
and hence can be bound more accurately by O(n))
|
HeapSort
Use Heap to sort an array
Heapsort(A)
{ A.heapsize = A.length();
build_heap(A);
for index = A.length() to 2 do
swap(A[1], A[index]);
A.heapsize = A.heapsize - 1;
heapify(A, 1);
}
Running Time:
Since heapify takes O(lgn) time and we only need to make n-1 calls
the algorithm runs in O(nlgn) time |
Applications of Heaps
- Heap sort: One of the best sorting methods being in-place and with no quadratic worst case scenarios.
- Selection algorithms: Finding the min, max or both of them, median or even any k-th element in sublinear time can be done dynamically with heaps.
- Graph algorithms: By using heaps as internal traversal data structures, run time will be reduced by an order of polynomial. Examples of such problems are Kruskal's minimal spanning tree algorithm and Dijkstra's shortest path problem.
|