I was not able to find a simple and friendly time or space complexity analysis for Heapsort. This is not a duplicate question on stackoveflow.
- Worst Time complexity let's get only this example, for heapsort it is O(n log(n)). How do we easily compute it?
Let's compare with the mergesort algorithm.
Mergesort
void mergeSort(int arr[], int l, int r) // T(n), n being the number of elements in arr
{
if (l < r)
{
........ // constant operations
mergeSort(arr, l, m); // T(n/2) since we apply it on aprox half
mergeSort(arr, m+1, r); // T(n/2) since we apply it on aprox half
merge(arr, l, m, r); // c*n , out of scope to analyse merge()
}
}
The purpose is to analyse the complexity, not the algorithm itself: https://www.geeksforgeeks.org/merge-sort/
Therefore, if n is the array's number of elements and c is a const, we have:
T(n) = c, if n=1
T(n) = 2*T(n/2) + c*n, if n>1
so we can rewrite
T(n) = 2*( 2*T(n/4) + c*n/2 ) +c*n
T(n) = 4*T(n/4) + 2cn
T(n) = 4*( 2T(n/8) + c*n/4 ) + 2cn
T(n) = 8*T(n/8) + 3c
...
T(n) = 2^k * T(n/2^k) + kcn
if we use T(1) that we know => 1 = n/2^k => k = log(n) =>
T(n) = 2^(log(n)) * T(1) + nlog(n)
T(n) = n + nlog(n)
=> nlog(n)
Full explanation: https://www.youtube.com/watch?v=0nlPxaC2lTw&list=PL2_aWCzGMAwKedT2KfDMB9YA5DgASZb3U&index=6
Now, let's get the example of heapsort.
I mention I already checked on stackoverflow, but there is no clear answer: Analysis of speed and memory for heapsort or heapsort - implementation's complexity
Heapsort
The purpose is to analyse the complexity, not the algorithm itself: https://www.geeksforgeeks.org/heap-sort/
// main function to do heap sort
void heapSort(int arr[], int n)
{
// Build heap (rearrange array)
for (int i = n / 2 - 1; i >= 0; i--)
heapify(arr, n, i); // n/2 * TH(n)
// One by one extract an element from heap
for (int i=n-1; i>0; i--)
{
// Move current root to end
swap(arr[0], arr[i]);
// call max heapify on the reduced heap
heapify(arr, i, 0); // (n-1) * TH(i)
}
}
T(n) = c, if n=1
TH is the time complexity for heapify()
T(n) = n/2 * TH(n) + (n-1) * TH(i) , where i is decreasing from n-1 to 1
The problem is how to calculate TH(n) = log(n)
.
Because based on it, T(n) = n*log(n)
Therefore, the code for heapify for which we need to compute TH(n):
// To heapify a subtree rooted with node i which is
// an index in arr[]. n is size of heap
void heapify(int arr[], int n, int i)
{
int largest = i; // Initialize largest as root
int l = 2*i + 1; // left = 2*i + 1
int r = 2*i + 2; // right = 2*i + 2
// If left child is larger than root
if (l < n && arr[l] > arr[largest])
largest = l;
// If right child is larger than largest so far
if (r < n && arr[r] > arr[largest])
largest = r;
// If largest is not root
if (largest != i)
{
swap(arr[i], arr[largest]);
// Recursively heapify the affected sub-tree
heapify(arr, n, largest); // how to express TH in terms of n ?
}
}
TH(n) = c, if n=1
worst case when the largest if never root:
TH(n) = c + ? * TH( ? )
how to write the recursive expression?
There is also the logical deduction, but let's avoid this strategy:
There are log(n) levels.
Half of the elements will be on the last layer, not touched by heapify().
So log(n) elements are touched.
This might be a good strategy, but not simple or friendly enough.
- Space complexity
How to compute O(1) as space complexity, since we use a heap of n elements? Or maybe the O(1) value is wrong : reference https://www.bigocheatsheet.com/ .