您的位置:首页 > 其它

数据量极大时用什么排序方法比较好

2013-04-13 17:52 211 查看
参考:点击打开链接

         点击打开链接

        点击打开链接

最近有一个88047579个double型数据的排序,采用的快速排序,但总是时不时的出问题:


Unhandled exception in XX.exe: 0xc00000FD; Stack Overflow

以及


Unhandled exception in XX.exe: 0xc00000FD; access violation

后来影响到数据量没那么大,本来可以正确执行的,也连带着出现这个错误。
在帖子点击打开链接中,说是堆栈溢出错误,要检查是否有死循环,以及提到可以修改堆栈大小,用动态数组。我都尝试了,但依然没有解决。

偶然间今天看到有人说是因为快速排序法递归调用次数太多,也会出现该问题。因此想到应该换一种适合极大数据量的排序方法。
点击打开链接上很多人对排序方法进行了比较。现总结一下。

1.在帖子点击打开链接中,有人提到:

当N很小时,快速排序慢,归并排序快 
当N很大时,并且有序程度高时,快速排序最快 
当N很大时,并且有序程序低时,堆排序最快

 
  快速排序是目前基于比较的内部排序中被认为是最好的方法,当待排序的关键字是随机分布时,快速排序的平均时间最短;
     堆排序所需的辅助空间少于快速排序,并且不会出现快速排序可能出现的最坏情况。这两种排序都是不稳定的。
     若要求排序稳定,则可选用归并排序。先利用直接插入排序求得较长的有序子文件,然后再两两归并之。因为直接插入排序是稳定的,所以改进后的归并排序仍是稳定的。

但是:由于快速排序不稳定,因此数据量极大时不如选用堆排序。

2.在帖子点击打开链接中,大多数人的结论都是堆排序比较好。
堆排序占花费是时间主要是在建堆的时候。所以在数据量方面来说,如果数据量越大,堆排序的优势就越明显。

大多数商用软件都采用快排,因为它在一般情况下是排序最快的算法。
然而,快排绝不能用于需要特定响应时间的系统,除非这个系统能承受O(n^2)的时间复杂度。
如果你预先估计可能会碰到这种最坏情况,那么
如果n比较小,改用插入排序——由于代码简单,它的时间复杂度的常数项比较少
如果n比较大,改用堆排序——你应该用堆排序,因为它能保证O(nlogn)的时间复杂度.

//堆排序

void BuildMaxHeap(int *,int );
void MaxHeapify(int *,int,int);
void heap_sort(int *,int ,int );


void swap(int *a, int m,int n)
{
int temp=a[m];
a[m]=a
;
a
=temp;
}


//测试堆排序
 
for( i=0; i<size; i++)
{
array0[i]=array_b[i];
}
i=heap_sort(array0,0,size-1);
cout<<"Heap Sort Running Time:"<<i<<endl;
fout<<"Heap Sort Running Time:"<<i<<endl;


void heap_sort(int *a,int start,int end)
{
int i;
int length=end-start;
int hsize=length;
BuildMaxHeap(a,hsize);
for( i=length; i>1; i--)
{
swap(a,1,i);
hsize--;
MaxHeapify(a,1,hsize);
}

}


void BuildMaxHeap(int *a,int size)
{
int i;
for( i=size/2; i>0; i--)
{
MaxHeapify(a,i,size);
}
}


void MaxHeapify(int *a,int i,int size)
{
int l,r,largest;
l=2*i;
r=2*i+1;
if(l<=size &&a[l]>a[i])
largest=l;
else
largest=i;
if(r<=size && a[r]>a[largest])
largest=r;
if(largest!= i)
{
swap(a,i,largest);
MaxHeapify(a,largest,size);
}
}


3.同时也指明了快速排序递归调用次数太多时会出现栈溢出,并给出了非递归版的快速排序法。
//快速排序
int partition(int *, int ,int );
void quick_sort(int *, int ,int);
void quick_sort_rec(int *, int ,int);

     //测试快速排序

  
for( i=0; i<size; i++)
{
array0[i]=array_b[i];
}
i=run_sort(quick_sort_rec,array0,0,size-1);
cout<<"Quick Sort Running Time:"<<i<<endl;
fout<<"Quick Sort Running Time:"<<i<<endl;


int partition(int *a,int low,int high)
{
int i,j;
int key=a[high];
i=low-1;
j=low;
for( ; j<high; j++)
{
if(a[j]<=key)
{
i++;
swap(a,i,j);
}
}
swap(a,i+1,high);
return i+1;
}

   

//递归调用次数太多 栈溢出!
void quick_sort_rec(int *a,int low,int high)
{
int mid;
if(low<high)
{
mid=partition(a,low,high);
quick_sort_rec(a,low,mid-1);
quick_sort_rec(a,mid+1,high);
}
}


//非递归版 --迭代
void quick_sort(int *base,int start,int end)
{
const int stacksize=1000;
int *stack=new int[stacksize];
int top=0;
stack[top++]=start;
stack[top++]=end-start+1;
while(top!=0)
{
//cout<<top<<endl;
top--;
int r=stack[top];
top--;
int p=stack[top];
if(p>=r)
continue;
int m=partition(base,p,r);
//push the left
stack[top++]=p;
stack[top++]=m-1;
//push the right
stack[top++]=m+1;
stack[top++]=r;
}
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: 
相关文章推荐