我最近尝试对一对整数的向量实现基数排序(其中第二个元素仅在第一个元素相等时才被考虑)。我这样做是通过两次计数排序 - 首先应用于对的第二个元素,然后是第一个元素。以下是我首先实现计数排序的方法:
//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)的时间复杂度,正如它应该具有的那样。
然后,我通过在10 ^ 6个元素的数组上运行它们,将此代码的运行时间与STL sort()(时间复杂度为O(nlog(n)))进行比较。令我惊讶的是,STL sort()最终表现略好于我的radix 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];
这一次,基数排序确实比STL排序()运行快5-6倍。这个观察让我想知道为什么我的第一个基数排序实现比第二个基本排序实现运行得慢得多,当它们都是O(n)时?
答案 0 :(得分:1)
您正在使用伪线性算法。它的复杂性是O(M)
其中
M = std::max_element(arr.begin(), arr.end())
您无法将其与std::sort
进行比较,其复杂度为O(N log(N))
N = arr.size()
第二个版本分配temp
一次,而第一个版本中的push_back
调用可能导致许多分配影响性能。
基数排序是一种不同的算法。请检查此link。