A priority queue with a limited size of N should do the job.
Put each element of the 2D array in the queue.
O(Arraysize * log2(N)) complexity.
Then the first element in the queue is the Nth smallest (assuming arry size >= N)
#include <stdio.h>
#include <stdlib.h>
typedef int PriorityQueue_T;
typedef struct {
PriorityQueue_T *A;
size_t Length;
size_t Size;
} PriorityQueue;
void PriorityQueue_Remove(PriorityQueue *Q) {
if (Q->Length > 0) {
size_t Index = 0;
while (1) {
size_t Mother = Index * 2 + 1;
size_t Father = Mother + 1;
if (Mother >= Q->Length) break;
if ((Q->A[Mother] < Q->A[Father]) || (Father >= Q->Length)) {
Q->A[Index] = Q->A[Mother];
Index = Mother;
} else {
Q->A[Index] = Q->A[Father];
Index = Father;
}
}
Q->Length--;
Q->A[Index] = Q->A[Q->Length];
while (Index > 0) {
size_t Child = (Index + 1)/ 2 - 1;
if (Q->A[Index] >= Q->A[Child]) {
break;
}
PriorityQueue_T tmp = Q->A[Index];
Q->A[Index] = Q->A[Child];
Q->A[Child] = tmp;
Index = Child;
}
}
}
void PriorityQueue_Insert(PriorityQueue *Q, PriorityQueue_T x) {
if (Q->Length < Q->Size || x > Q->A[0]) {
if (Q->Length >= Q->Size) {
PriorityQueue_Remove(Q);
}
size_t Index = Q->Length++;
Q->A[Index] = x;
while (Index > 0) {
size_t Child = (Index + 1)/ 2 - 1;
if (Q->A[Index] >= Q->A[Child]) {
break;
}
PriorityQueue_T tmp = Q->A[Index];
Q->A[Index] = Q->A[Child];
Q->A[Child] = tmp;
Index = Child;
}
}
}
// Pseudo code here to end
void PQ_FindNthSmallest(PriorityQueue_T Array[W][H], size_t N) {
PriorityQueue Q;
Q.Length = 0;
Q.Size = N;
Q.A = malloc(Q.Size * sizeof(PriorityQueue_T));
For each element in the array
PriorityQueue_Insert(&Q, Array[x][y]);
printf("Nth smallest: %CorrespondingFormat", Q.A[0]);
free(Q.A);
}