Write a function that prints the \(k^{th}\) largest elements in an array. Elements in array can be in any order.
For example, if given array is [1, 23, 12, 9, 30, 2, 50] and you are asked for the largest 3 elements i.e., \(k\) = 3 then your program should print 50, 30 and 23.
Method:
- Build a Max Heap tree in \(O(n)\)
- Extract the max \(k\) times to get \(k\) maximum elements from the Max Heap in \(O(k\log{n})\)
Time complexity: \(O(n + k\log{n})\)
Difficulty level
This exercise is mostly suitable for students
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include<conio.h>
#define N 20
typedef struct node
{
int *array;
int count; // Number of elements in the heap
int capacity; // Size of the heap
int heap_type; //0: Min heap or 1: Max heap
} *Heap;
Heap CreateHeap(int capacity, int heap_type)
{
Heap h = (Heap)malloc(sizeof(struct node));
h->heap_type = heap_type;
h->count = 0;
h->capacity = capacity;
h->array = (int *)malloc(sizeof(int)*h->capacity);
if (!h->array) return NULL;
return h;
}
int Parent(Heap h, int i)
{
if (i <= 0 || i >= h->count)
return -1;
return ((i - 1) / 2);
}
int LeftChild(Heap h, int i)
{
int left = 2 * i + 1;
if (left >= h->count) return -1;
return left;
}
int RightChild(Heap h, int i)
{
int right = 2 * i + 2;
if (right >= h->count)
return -1;
return right;
}
int GetMaximum(Heap h)
{
if (h->count == 0)
return -1;
return h->array[0];
}
void PercolateDown(Heap *h, int i) // Heapifying an element at location i
{
int l, r, max, temp;
l = LeftChild(*h, i);
r = RightChild(*h, i);
if (l != -1 && (*h)->array[l]>(*h)->array[i])
max = l;
else
max = i;
if (r != -1 && (*h)->array[r]>(*h)->array[max])
max = r;
if (max != i)
{ // Swap h->array[i] and h->array[max];
temp = (*h)->array[i];
(*h)->array[i] = (*h)->array[max];
(*h)->array[max] = temp;
PercolateDown(h, max);
}
}
int DeleteMax(Heap *h)
{
int data;
if ((*h)->count == 0)
return -1;
data = (*h)->array[0];
(*h)->array[0] = (*h)->array[(*h)->count - 1];
(*h)->count--;
PercolateDown(h, 0);
return data;
}
void ResizeHeap(Heap *h)
{
int i;
int *array_old = (*h)->array;
(*h)->array = (int *)malloc(sizeof(int)*(*h)->capacity * 2);
/* if(!(*h)->array)
exit(-1); */
for (i = 0; i<(*h)->capacity; i++)
(*h)->array[i] = array_old[i];
(*h)->capacity *= 2;
free(array_old);
}
int Insert(Heap *h, int data)
{
int i;
if ((*h)->count == (*h)->capacity)
ResizeHeap(h);
(*h)->count++; //increasing the heap size to hold this new item
i = (*h)->count - 1;
while (i>0 && data > (*h)->array[(i - 1) / 2])
{
(*h)->array[i] = (*h)->array[(i - 1) / 2];
i = (i - 1) / 2;
}
(*h)->array[i] = data;
}
void DestroyHeap(Heap *h)
{
if (h == NULL) return;
free((*h)->array);
free(h);
h = NULL;
}
void BuildHeap(Heap *h, int A[], int n)
{
int i;
if (h == NULL) return;
while (n > (*h)->capacity)
ResizeHeap(h);
for (i = 0; i<n; i++)
(*h)->array[i] = A[i];
(*h)->count = n;
for (i = (n - 1) / 2; i >= 0; i--)
{
PercolateDown(h, i);
}
}
void HeapSort(int A[], int n)
{
Heap h = CreateHeap(n, 1);
int old_size, i, temp;
BuildHeap(&h, A, n);
old_size = h->count;
for (i = n - 1; i >= 0; i--)
{ //h->array[0] is the largest element
temp = h->array[0];
h->array[0] = h->array[h->count - 1];
h->array[h->count - 1] = temp;
h->count--;
PercolateDown(&h, 0);
}
h->count = old_size;
for (i = 0; i<h->count; i++)
A[i] = h->array[i];
}
void print_max(int A[], int n, int k)
{
Heap h = CreateHeap(n, 1);
BuildHeap(&h, A, n);
while (k--)
printf("%d \n", DeleteMax(&h));
}
int main()
{
int tab[N], size, i, k;
printf("Enter the number of elements in the array\n");
scanf("%d", &size);
printf("Enter %d integers\n", size);
for (i = 0; i < size; i++)
scanf("%d", &tab[i]);
printf("Enter k\n");
scanf("%d", &k);
print_max(tab, size, k);
getch();
return 0;
}
Back to the list of exercises
Looking for a more challenging exercise, try this one !!
Derivative and second derivative