我遇到以下代码的问题:
class quicksort {
private:
void _sort(double_it begin, double_it end)
{
if ( begin == end ) { return ; }
double_it it = partition(begin, end, bind2nd(less<double>(), *begin)) ;
iter_swap(begin, it-1);
_sort(begin, it-1);
_sort(it, end);
}
public:
quicksort (){}
void operator()(vector<double> & data)
{
double_it begin = data.begin();
double_it end = data.end() ;
_sort(begin, end);
}
};
然而,这对于太多的元素不起作用(它适用于10 000个元素,但不适用于10万个元素)。
示例代码:
int main()
{
vector<double>v ;
for(int i = n-1; i >= 0 ; --i)
v.push_back(rand());
quicksort f;
f(v);
return 0;
}
STL分区功能是否适用于此类尺寸?或者我错过了什么?
非常感谢你的帮助。
答案 0 :(得分:2)
我看到了几个问题。我不会在您的分区中包含数据透视表,所以我会改用此行:
double_it it = partition(begin + 1, end, bind2nd(less<double>(), *begin)) ;
此外,我不会继续在未来的种类中包含枢轴,所以我会这样做
_sort(begin, it - 2);
相反,但您需要注意it - 2
不小于begin
,因此请先检查it - 1 != begin
。没有必要不断地对枢轴进行排序 - 它已经在正确的位置。这只会增加许多额外的不必要的递归。
即使在更改之后,您仍然可以使用此代码存在堆栈溢出问题。例如,如果使用此代码对已排序的数组进行排序,则性能将为O(N ^ 2),如果N非常大,则会出现堆栈溢出。使用随机选择的pivot将基本上消除排序数组问题,但如果数组是完全相同的元素,您仍然可能会遇到问题。在这种情况下,您需要更改算法以使用Bentley-McIlroy分区等。或者您可以将其更改为introsort并在递归深度变深时更改为heapsort。
答案 1 :(得分:1)
您是否检查过doublt_it it
未被设置为begin
的值?这会导致行iter_swap(begin, it-1);
出现问题。
不是吗?
好吧,猜测#2是堆栈溢出,因为你会进行太多的递归。某些编译器无法处理许多递归循环。 100k可能只有10k它可以处理。
答案 2 :(得分:0)
检查以下代码。我写得很快,没有模板化和使用迭代器,但我的想法是证明quicksort可以排序大型数组(这很明显,他 - 他)。
所以,你的算法术语中的快速排序有问题,而不是堆栈溢出/其他编译器的东西。我的意思是,你应该总是试着了解导致什么的原因并消除“深层”问题,而不是“浅层”问题。
请注意,我的代码可以使用与代码中相同的迭代器方法轻松重写(可能需要一些额外的检查,但无论如何,它很容易实现)。
#include <vector>
#include <algorithm>
#include <utility>
#include <functional>
class sorter {
public:
sorter(std::vector<int>& data) : data(data) { }
void quicksort(int p, int r) {
if (p < r) {
int q = std::partition(data.begin() + p, data.begin() + r, std::bind2nd(std::less<int>(), data[r])) - data.begin();
std::swap(data[q], data[r]);
quicksort(p, q - 1);
quicksort(q + 1, r);
}
}
void sort() {
quicksort(0, data.size() - 1);
}
private:
std::vector<int>& data;
};
int main() {
size_t n = 1000000;
std::vector<int> v;
for(int i = n - 1; i >= 0 ; --i)
v.push_back(rand());
sorter s(v);
s.sort();
return 0;
}
#
编辑迭代器的东西意味着类似
class sorter {
public:
typedef std::vector<int> data_type;
sorter(std::vector<int>& data) : data(data) { }
void quicksort(data_type::iterator p, data_type::iterator r) {
data_type::iterator q = std::partition(p, r, std::bind2nd(std::less<int>(), *r));
std::iter_swap(q, r);
if (q != p)
quicksort(p, q - 1);
if (q != r)
quicksort(q + 1, r);
}
void sort() {
quicksort(data.begin(), data.end() - 1);
}
private:
std::vector<int>& data;
};