Quicksort /矢量/分区问题

时间:2010-05-26 13:30:35

标签: c++ stl quicksort data-partitioning

我遇到以下代码的问题:

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分区功能是否适用于此类尺寸?或者我错过了什么?

非常感谢你的帮助。

3 个答案:

答案 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;
};