使用整数向量的向量对整数向量进行基数排序
Posted
技术标签:
【中文标题】使用整数向量的向量对整数向量进行基数排序【英文标题】:Radix sorting a vector of ints using a vector of int vectors 【发布时间】:2013-08-16 20:00:31 【问题描述】:我最近尝试为一对整数向量实现基数排序(其中仅当第一个元素相等时才考虑第二个元素)。我通过两次应用计数排序来做到这一点 - 首先是对的第二个元素,然后是第一个元素。以下是我最初实现计数排序的方式:
//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];
这一次,基数排序的运行速度确实比 STL sort() 快了大约 5-6 倍。这个观察让我想知道为什么我的第一个基数排序实现比第二个运行慢得多,而它们都是 O(n)?
【问题讨论】:
【参考方案1】:您正在使用伪线性算法。它的复杂性是O(M)
哪里
M = std::max_element(arr.begin(), arr.end())
您无法将其与复杂度为 O(N log(N))
的 std::sort
进行比较
N = arr.size()
第二个版本分配一次temp
,而第一个版本中的push_back
调用会导致很多分配影响性能。
基数排序是一种不同的算法。检查这个link。
【讨论】:
首先,不是应用基数排序来对一个数字数组进行一次排序,而是使用它来对一个整数对数组进行排序,使用相同的基本原理。其次,正如我在问题中的代码 sn-ps 中提到的 cmets ,在我的情况下 M = N-1 。至于导致减速的 push_back 调用,可能是这种情况,但考虑到它对性能的影响程度(在我的 i5-3230 机器上运行一百万个元素时差异 > 10 秒),我会认为有点不太可能。 例如,将一百万个元素输入到预先分配大小的向量中的程序仅比将一百万个元素推入其中的程序快几毫秒(至少在我的机器上) .以上是关于使用整数向量的向量对整数向量进行基数排序的主要内容,如果未能解决你的问题,请参考以下文章