Counting sort
- Count the number of students for each rank;
- Use the cumulative counts to find the index of the first student of every rank;
- Put the students at the first available index for their rank.
Each of these three steps has complexity O(n+k), where n is the number of students and k the number of ranks.
I'll show an example with 10 students, with ranks going from 0 to 2 instead of 0 to 100.
# define NBSTUDENTS 10
# define NBRANKS 3
struct Student students[NBSTUDENTS] =
{("Alice", 0), ("Bob", 2), ("Charlie", 1), ("Daenerys", 1), ("Eleonore", 2),
("Farouk", 1), ("Gabriel", 0), ("Hector", 1), ("Iris", 2), ("Julien", 2)};
- Count the number of students for each rank
int count_per_rank[NBRANKS] = {2, 4, 4};
- Use the cumulative counts to find the index of the first student of every rank
int available_index[NBRANKS] = {0, 0+2, 0+2+4};
You can use std::partial_sum defined in header <numeric> to get the cumulative counts; see Surt's answer.
- Put the students at the first available index for their rank
struct Student sorted_students[NBSTUDENTS] = {}
for (auto student = students.begin(); student < students.end(); ++student)
{
sorted_students[available_index[student->rank]] = *student;
available_index[student->rank]++;
}
std::sort
The complexity of std::sort is O(n log(n)). The complexity of the counting sort above is O(n+k). These O( ) notation hide a constant; you can expect that constant to be much smaller for the well-optimised std::sort than for your custom implemented sort. When n tends towards infinity, log(n) also tends towards infinity. But log increases very slowly. How big is your big size input? I assume you have fewer than a million students. The binary logarithm of 1000000 is 20. If we assume n < 1000000, then n log(n) < 20 n. Are we really faster than std::sort with our custom counting sort?