Недавно я попытался реализовать сортировку по основанию для вектора пары целых чисел (где второй элемент рассматривается только тогда, когда первые элементы равны). Я сделал это, дважды применив сортировку подсчетом — сначала ко второму элементу пары, а затем к первому элементу. Вот как я сначала реализовал сортировку подсчетом:
//vector to be sorted (of size n).
vector<int> arr;
//arr gets filled here
//N-1 is the maximum number which can occur in the array. N was equal to n in my case
vector<vector<int> > mat(N);
for (int i=0;i<n;i++)
{
mat[arr[i]].push_back(i);
}
//array in which the sorted array will be stored
vector<int> arr2;
for (int i=0;i<N;i++)
{
for(int j=0;j<sz(mat[i]);j++) arr2.push_back(arr1[mat[i][j]]);
}
Очевидно, что первый цикл for выполняется за O(n). Поскольку массив «mat» содержит ровно n элементов, доступ к нему будет осуществляться не более 2n раз во втором (вложенном) цикле. Это означает, что приведенный выше код имеет временную сложность O(n), как и должно быть.
Затем я сравнил время выполнения этого кода с STL sort() (который имеет временную сложность O(nlog(n))), запустив оба из них на массиве из 10 ^ 6 элементов. К моему большому удивлению, STL sort() оказалась немного лучше, чем моя реализация поразрядной сортировки.
Затем я изменил свою реализацию сортировки подсчета на следующую:
//vector to be sorted (of size n).
vector<int> arr;
//arr gets filled here
//N-1 is the maximum number which can occur in the array. N was equal to n in my case
vector<int> temp(N,0);
for(int i=0;i<n;i++) temp[arr[i]]++;
for(int i=1;i<N;i++) temp[i]+=temp[i-1];
//array in which the sorted array will be stored
vector<int> arr2(n);
for(int i=n-1;i>=0;i--) arr2[--temp[arr[i]]]=arr[i];
На этот раз поразрядная сортировка работала примерно в 5-6 раз быстрее, чем STL sort(). Это наблюдение заставило меня задуматься, почему моя первая реализация поразрядной сортировки работает намного медленнее, чем вторая, когда обе они равны O(n)?