对比 几种 排序算法 的 比较次数
今天在实际项目中遇到了一个排序问题,对Object排序,其中比较操作特别耗时,而交换操作的时间可以忽略不计,这样就不能用之前一直了解的最佳实践的快速排序了,得重新评价各种排序算法的比较次数,因此做了以下实验:对比了在处理相同长度的随机数组排序时,各种排序的比较次数:
实验结果输出如下:(注:里面InsertSort使用的是二分插入排序)
10 numbers: BubbleSort: 30 SelectSort: 45 InsertSort: 21 MergeSort: 24 QuickSort: 22 100 numbers: BubbleSort: 3725 SelectSort: 4950 InsertSort: 523 MergeSort: 547 QuickSort: 633 1000 numbers: BubbleSort: 374250 SelectSort: 499500 InsertSort: 8576 MergeSort: 8716 QuickSort: 11403 10000 numbers: BubbleSort: 37487499 SelectSort: 49995000 InsertSort: 117629 MergeSort: 120386 QuickSort: 157664 100000 numbers: BubbleSort: -544992296 SelectSort: 704982704 InsertSort: 1391899 MergeSort: 1536293 QuickSort: 2061112
从实验结果可以看出,实践最好的是二分插入排序,有最少的比较次数。
其次是归并排序,最快排序表现一般,而那两个O(n^2)的就明显差得远了(100000时他们溢出了)
附代码:
#include<iostream> #include<cstdio> #include<ctime> using namespace std; const int LENGTH=100000; const int Max_num=65535123; void printNums(int *pnum,int l) { for(int i=0;i<l;i++) { cout<<pnum[i]<<" "; } cout<<endl; } int BubbleSort(int* pnum) { int sorting[LENGTH]; for(int i=0;i<LENGTH;i++) { sorting[i]=pnum[i]; } int compareCount=0; //sort for(int i=LENGTH-1;i>0;i--) { int changeCount=0; for(int j=i;j>0;j--) { compareCount++; if(sorting[j]<sorting[j-1]) { sorting[j]^=sorting[j-1]; sorting[j-1]^=sorting[j]; sorting[j]^=sorting[j-1]; changeCount++; } } if(!changeCount) { break; } } //printNums(sorting,LENGTH); return compareCount; } int SelectSort(int* pnum) { int sorting[LENGTH]; for(int i=0;i<LENGTH;i++) { sorting[i]=pnum[i]; } int compareCount=0; //sort for(int i=0;i<LENGTH-1;i++) { int t=i; for(int j=i+1;j<LENGTH;j++) { compareCount++; if(sorting[j]<sorting[t]) t=j; } if(t!=i) { sorting[t]^=sorting[i]; sorting[i]^=sorting[t]; sorting[t]^=sorting[i]; } } //printNums(sorting,LENGTH); return compareCount; } int InsertSort(int* pnum) { int sorting[LENGTH]; for(int i=0;i<LENGTH;i++) { sorting[i]=pnum[i]; } int compareCount=0; //sort for(int i=1;i<LENGTH;i++) { int beginIndex=0; int endIndex=i-1; int pos=-1; while(beginIndex<=endIndex) { int middleIndex=(beginIndex+endIndex)/2; compareCount++; if(sorting[i]>sorting[middleIndex]) { beginIndex=middleIndex+1; if(beginIndex>endIndex) { pos=endIndex+1; } } else if(sorting[i]<sorting[middleIndex]) { endIndex=middleIndex-1; if(beginIndex>endIndex) { pos=beginIndex; } } else { pos=middleIndex+1; break; } } if(pos>=0&&pos<i) { int temp=sorting[i]; for(int j=i-1;j>=pos;j--) { sorting[j+1]=sorting[j]; } sorting[pos]=temp; } } //printNums(sorting,LENGTH); return compareCount; } int merge(int *pnum,int p,int q,int r) { int count=0; int n1=q-p+1; int n2=r-q; int* pL=new int[n1]; int* pR=new int[n2]; for(int i=0;i<n1;i++) { pL[i]=pnum[p+i]; } for(int i=0;i<n2;i++) { pR[i]=pnum[q+i+1]; } //pL[n1]=Max_num; //pR[n2]=Max_num; int i,j,k; for(i=0,j=0,k=p;k<=r;k++) { count++; if(pL[i]<=pR[j]) { pnum[k]=pL[i++]; if(i>=n1) { for(;k<r;k++) { pnum[k+1]=pR[j++]; } break; } } else { pnum[k]=pR[j++]; if(j>=n2) { for(;k<r;k++) { pnum[k+1]=pL[i++]; } break; } } } return count; } int merge_sort(int *pnum,int p,int r) { int count=0; if(p<r) { int q=(p+r)/2; count+=merge_sort(pnum,p,q); count+=merge_sort(pnum,q+1,r); count+=merge(pnum,p,q,r); } return count; } int MergeSort(int *pnum) { int sorting[LENGTH]; for(int i=0;i<LENGTH;i++) { sorting[i]=pnum[i]; } int compareCount=0; //sort compareCount=merge_sort(sorting,0,LENGTH-1); //printNums(sorting,LENGTH); return compareCount; } int partition(int *pnum,int p,int r,int &q) { int count=0; int x=pnum[r]; int i=p-1; for(int j=p;j<r;j++) { count++; if(pnum[j]<=x) { i++; int t=pnum[i]; pnum[i]=pnum[j]; pnum[j]=t; } } int t=pnum[i+1]; pnum[i+1]=pnum[r]; pnum[r]=t; q=i+1; return count; } int quick_sort(int *pnum,int p,int r) { int count=0; if(p<r) { int q=-1; count+=partition(pnum,p,r,q); count+=quick_sort(pnum,p,q-1); count+=quick_sort(pnum,q+1,r); } return count; } int QuickSort(int *pnum) { int sorting[LENGTH]; for(int i=0;i<LENGTH;i++) { sorting[i]=pnum[i]; } int compareCount=0; //printNums(sorting,LENGTH); //sort compareCount=quick_sort(sorting,0,LENGTH-1); //printNums(sorting,LENGTH); return compareCount; } int main() { srand((unsigned int)time(0)); int num[LENGTH]; memset(num,0,sizeof(num)); for(int i=0;i<LENGTH;i++) { num[i]=rand()%Max_num; } cout<<LENGTH<<" numbers:"<<endl; int count=BubbleSort(num); cout<<"BubbleSort:\t"<<count<<endl; count=SelectSort(num); cout<<"SelectSort:\t"<<count<<endl; count=InsertSort(num); cout<<"InsertSort:\t"<<count<<endl; count=MergeSort(num); cout<<"MergeSort:\t"<<count<<endl; count=QuickSort(num); cout<<"QuickSort:\t"<<count<<endl; return 0; }