八種排序算法效率比較

     從剛上大一那會兒學的C語言開始,就已經接觸到了很多排序算法,但當時都只是爲了完成簡單的排序任務而已,並且所給的數據也不夠多,因此看不出各個排序算法間的執行效率的優劣。最近有個數據結構課程設計的實驗,是有關於排序算法之間的效率比較,我就順便把它放上來了,並對各個算法執行的效率時間作了柱形統計圖表。這次實驗主要測試了8種排序算法:插入排序、快速排序、冒泡排序、希爾排序、簡單選擇排序、堆排序、歸併排序、折半插入排序。 算法

      總共創建了三種狀況,分別是平均排序、最好狀況排序、最壞狀況排序。第一種狀況就是使用了VC6.0下的隨機數生成函數輸出100000個隨機數進行排序;第二種狀況是100000個數自己已經按從小到大的順序排列了;第三種狀況就是100000個數所有是按逆序排列。代碼以下: windows

#include<stdio.h>
#include<stdlib.h>
#include<time.h>
#include<windows.h>
#define MAX 100000
 
void InsSort(int r[],int length)
{
 int i,j;
 for (i=2;i<=length;i++)
 {
 r[0]=r[i];
 j=i-1;
 while(r[0]<r[j])
 {
 r[j+1]=r[j];
 j=j-1;
 }
 r[j+1]=r[0];
 }
}       //插入排序
 
void swap(int &x,int &y)
{
 int z;
 z=x;
 x=y;
 y=z;
}
int median3(int a[],int left,int right)
{
 int center=(left+right)/2;
 if(a[left]>a[center])
 swap(a[left],a[center]);
 if(a[left]>a[right])
 swap(a[left],a[right]);
 if(a[center]>a[right])
 swap(a[center],a[right]);
 swap(a[center],a[right-1]);
 return a[right-1];
}
void insertionsort(int a[],int n)
{
 int j,p;
 int tmp;
 for(p=1;p<=n;p++)
 {
 tmp=a[p];
 for(j=p;j>0&&a[j-1]>tmp;j--)
 a[j]=a[j-1];
 a[j]=tmp;
 }
}
void qsort(int a[],int left,int right)
{
 int i,j;
 int pivot;
 if(left+2<=right)
 {
 pivot=median3(a,left,right);
 i=left;j=right-1;
 for(;;)
 {
 while(a[++i]<pivot){}
 while(a[--j]>pivot){}
 if(i<j)
 swap(a[i],a[j]);
 else
 break;
 }
 swap(a[i],a[right-1]);
 qsort(a,left,i-1);
 qsort(a,i+1,right);
 }
 else
 insertionsort(a+left,right-left+1);
}
void quicksort(int a[],int n)
{
 qsort(a,0,n-1);
}      //快速排序
 
void BubbleSort(int r[],int length)
{
 int i,j,temp;
 for(j=length;j>0;j--)
 for(i=0;i<j-1;i++)
 if(r[i]>r[i+1])
 {
 temp=r[i];
 r[i]=r[i+1];
 r[i+1]=temp;
 }
}      //冒泡排序
 
void ShellInsert(int r[],int length,int delta)
{
 int i,j;
 for(i=1+delta;i<=length;i++)
 if(r[i]<r[i-delta])
 {
 r[0]=r[i];
 for(j=i-delta;j>0&&r[0]<r[j];j-=delta)
 r[j+delta]=r[j];
 r[j+delta]=r[0];
 }
}
void  ShellSort(int r[], int length, int delt[], int n)
{ 
 int i;
 for(i=0;i<=n-1;++i)
 ShellInsert(r,length,delt[i]);
}       //希爾排序
 
void SelectSort(int r[],int length)
{
 int i,j,k;
 int n;
 int x;
    n=length;
 for (i=1;i<=n-1;++i)
 {
 k=i;
 for(j=i+1;j<=n;++j)
 if(r[j]<r[k])
 k=j;
 if( k!=i)
 {
 x= r[i];
 r[i]=r[k];
 r[k]=x;
 }
 }
 
}        //簡單選擇排序
 
void sift(int r[],int k,int m)
{
 int t;
 int i,j;
 int x;
 int finished;
 t= r[k];
 x=r[k];
 i=k;
 j=2*i;
 finished=FALSE;
 while(j<=m&&!finished)
 {     
 if(j<m&&r[j]< r[j+1])
 j=j+1;
 if(x>=r[j])
 finished=TRUE;
 else 
 {
 r[i]=r[j];
 i=j;
 j=2*i;
 }
 }
 r[i] =t;
}
void crt_heap(int r[], int length)
{
 int i,n;
    n=length;
 for (i=n/2;i>=1;--i) 
 sift(r,i,n);
}
void HeapSort(int r[],int length)
{
 int i,n;
 int b;
 crt_heap(r,length);
 n= length;
 for (i=n;i>=2;--i)
 {
 b=r[1];
 r[1]=r[i];
 r[i]=b;
 sift(r,1,i-1);
 }
}       //堆排序
 
void merge(int a[],int tmparray[],int lpos,int rpos,int rightend)
{
 int i,leftend,numelements,tmppos;
 leftend=rpos-1;
 tmppos=lpos;
 numelements=rightend-lpos+1;
 while(lpos<=leftend && rpos<=rightend)
 if(a[lpos]<=a[rpos])
 tmparray[tmppos++]=a[lpos++];
 else
 tmparray[tmppos++]=a[rpos++];
 while(lpos<=leftend)
 tmparray[tmppos++]=a[lpos++];
 while(rpos<=rightend)
 tmparray[tmppos++]=a[rpos++];
 for(i=0;i<numelements;i++,rightend--)
 a[rightend]=tmparray[rightend];
}
void msort(int a[],int tmparray[],int left,int right)
{
 int center;
 if(left<right)
 {
 center=(left+right)/2;
 msort(a,tmparray,left,center);
 msort(a,tmparray,center+1,right);
 merge(a,tmparray,left,center+1,right);
 }
}
void mergesort(int a[],int n)
{
 int *tmparray;
 tmparray=(int*)malloc(n*sizeof(int));
 if(tmparray!=NULL)
 {
 msort(a,tmparray,0,n-1);
 free(tmparray);
 }
 else
 printf("no space for tmp array!");
}        //歸併排序
 
void BInsertSort(int num[],int n)
{
 int length=n;
 int low,high,i,j,m;
 for(i=2;i<=length;i++)
 {
   num[0]=num[i];
   low=1;
   high=i-1;
   while(low<=high)
   {
   m=(low+high)/2;
 if(num[0]<num[m])
 high=m-1;
 else
 low=m+1;
   }
   for(j=i-1;j>=high+1;j--)
   num[j+1]=num[j];
   num[high+1]=num[0];
 }
}        //折半插入排序
 
void main()
{
 long dwStart,dwStop,runtime;
 int num[MAX],a[MAX],i,j;
 dwStart=GetTickCount();
 srand((unsigned)time(NULL));
 for(i=0;i<MAX;i++)
 num[i]=rand(); 
 dwStop=GetTickCount();
 runtime=dwStop-dwStart;
 printf("生成%d個隨機數運行了%ldms\n\n",MAX,runtime);
 
 printf("********平均排序時間********\n");
 for(i=0;i<MAX;i++)
 a[i]=num[i];
 dwStart=GetTickCount();
 InsSort(a,MAX);
 dwStop=GetTickCount();
 runtime=dwStop-dwStart;
 printf("使用插入排序運行了%ldms\n",runtime);
 
 for(i=0;i<MAX;i++)
 a[i]=num[i];
 dwStart=GetTickCount();
 quicksort(a,MAX);
 dwStop=GetTickCount();
 runtime=dwStop-dwStart;
 printf("使用快速排序運行了%ldms\n",runtime);
 
 for(i=0;i<MAX;i++)
 a[i]=num[i];
 dwStart=GetTickCount();
 BubbleSort(a,MAX);
 dwStop=GetTickCount();
 runtime=dwStop-dwStart;
 printf("使用冒泡排序運行了%ldms\n",runtime);
 
 int delt[10]={100,80,60,40,20,10,5,3,2,1};
 for(i=0;i<MAX;i++)
 a[i]=num[i];
 dwStart=GetTickCount();
 ShellSort(a,MAX,delt,10);
 dwStop=GetTickCount();
 runtime=dwStop-dwStart;
 printf("使用希爾排序運行了%ldms\n",runtime);
 
 for(i=0;i<MAX;i++)
 a[i]=num[i];
 dwStart=GetTickCount();
 SelectSort(a,MAX);
 dwStop=GetTickCount();
 runtime=dwStop-dwStart;
 printf("使用簡單選擇排序運行了%ldms\n",runtime);
 
 for(i=0;i<MAX;i++)
 a[i]=num[i];
 dwStart=GetTickCount();
 HeapSort(a,MAX);
 dwStop=GetTickCount();
 runtime=dwStop-dwStart;
 printf("使用堆排序運行了%ldms\n",runtime);
 
 for(i=0;i<MAX;i++)
 a[i]=num[i];
 dwStart=GetTickCount();
 mergesort(a,MAX);
 dwStop=GetTickCount();
 runtime=dwStop-dwStart;
 printf("使用歸併排序運行了%ldms\n",runtime);
 
 for(i=0;i<MAX;i++)
 a[i]=num[i];
 dwStart=GetTickCount();
 BInsertSort(a,MAX);
 dwStop=GetTickCount();
 runtime=dwStop-dwStart;
 printf("使用折半插入排序運行了%ldms\n",runtime);
 printf("****************************\n\n");
 
 printf("******最好狀況排序時間******\n");
 for(i=0;i<MAX;i++)
 a[i]=i;
 dwStart=GetTickCount();
 InsSort(a,MAX);
 dwStop=GetTickCount();
 runtime=dwStop-dwStart;
 printf("使用插入排序運行了%ldms\n",runtime);
 
 for(i=0;i<MAX;i++)
 a[i]=i;
 dwStart=GetTickCount();
 quicksort(a,MAX);
 dwStop=GetTickCount();
 runtime=dwStop-dwStart;
 printf("使用快速排序運行了%ldms\n",runtime);
 
 for(i=0;i<MAX;i++)
 a[i]=i;
 dwStart=GetTickCount();
 BubbleSort(a,MAX);
 dwStop=GetTickCount();
 runtime=dwStop-dwStart;
 printf("使用冒泡排序運行了%ldms\n",runtime);
 
 for(i=0;i<MAX;i++)
 a[i]=i;
 dwStart=GetTickCount();
 ShellSort(a,MAX,delt,10);
 dwStop=GetTickCount();
 runtime=dwStop-dwStart;
 printf("使用希爾排序運行了%ldms\n",runtime);
 
 for(i=0;i<MAX;i++)
 a[i]=i;
 dwStart=GetTickCount();
 SelectSort(a,MAX);
 dwStop=GetTickCount();
 runtime=dwStop-dwStart;
 printf("使用簡單選擇排序運行了%ldms\n",runtime);
 
 for(i=0;i<MAX;i++)
 a[i]=i;
 dwStart=GetTickCount();
 HeapSort(a,MAX);
 dwStop=GetTickCount();
 runtime=dwStop-dwStart;
 printf("使用堆排序運行了%ldms\n",runtime);
 
 for(i=0;i<MAX;i++)
 a[i]=i;
 dwStart=GetTickCount();
 mergesort(a,MAX);
 dwStop=GetTickCount();
 runtime=dwStop-dwStart;
 printf("使用歸併排序運行了%ldms\n",runtime);
 
 for(i=0;i<MAX;i++)
 a[i]=i;
 dwStart=GetTickCount();
 BInsertSort(a,MAX);
 dwStop=GetTickCount();
 runtime=dwStop-dwStart;
 printf("使用折半插入排序運行了%ldms\n",runtime);
 printf("****************************\n\n");
 
 printf("******最壞狀況排序時間******\n");
 for(i=MAX-1,j=0;i<=0,j<MAX;i--,j++)
 a[j]=i;
 dwStart=GetTickCount();
 InsSort(a,MAX);
 dwStop=GetTickCount();
 runtime=dwStop-dwStart;
 printf("使用插入排序運行了%ldms\n",runtime);
 
 for(i=MAX-1,j=0;i<=0,j<MAX;i--,j++)
 a[j]=i;
 dwStart=GetTickCount();
 quicksort(a,MAX);
 dwStop=GetTickCount();
 runtime=dwStop-dwStart;
 printf("使用快速排序運行了%ldms\n",runtime);
 
 for(i=MAX-1,j=0;i<=0,j<MAX;i--,j++)
 a[j]=i;
 dwStart=GetTickCount();
 BubbleSort(a,MAX);
 dwStop=GetTickCount();
 runtime=dwStop-dwStart;
 printf("使用冒泡排序運行了%ldms\n",runtime);
 
 for(i=MAX-1,j=0;i<=0,j<MAX;i--,j++)
 a[j]=i;
 dwStart=GetTickCount();
 ShellSort(a,MAX,delt,10);
 dwStop=GetTickCount();
 runtime=dwStop-dwStart;
 printf("使用希爾排序運行了%ldms\n",runtime);
 
 for(i=MAX-1,j=0;i<=0,j<MAX;i--,j++)
 a[j]=i;
 dwStart=GetTickCount();
 SelectSort(a,MAX);
 dwStop=GetTickCount();
 runtime=dwStop-dwStart;
 printf("使用簡單選擇排序運行了%ldms\n",runtime);
 
 for(i=MAX-1,j=0;i<=0,j<MAX;i--,j++)
 a[j]=i;
 dwStart=GetTickCount();
 HeapSort(a,MAX);
 dwStop=GetTickCount();
 runtime=dwStop-dwStart;
 printf("使用堆排序運行了%ldms\n",runtime);
 
 for(i=MAX-1,j=0;i<=0,j<MAX;i--,j++)
 a[j]=i;
 dwStart=GetTickCount();
 mergesort(a,MAX);
 dwStop=GetTickCount();
 runtime=dwStop-dwStart;
 printf("使用歸併排序運行了%ldms\n",runtime);
 
 for(i=MAX-1,j=0;i<=0,j<MAX;i--,j++)
 a[j]=i;
 dwStart=GetTickCount();
 BInsertSort(a,MAX);
 dwStop=GetTickCount();
 runtime=dwStop-dwStart;
 printf("使用折半插入排序運行了%ldms\n",runtime);
 printf("****************************\n");
 
 printf("\n排序測試完成!");
 getchar();
}

      執行程序是個很漫長的過程,像對於冒泡排序之類的算法,十萬個數的排序再好的機器也得算上半天,不過像快速排序之類的算法若是不給予足夠多的數據的話,執行時間永遠是0毫秒。因此爲了測算精確和公平比較,時間長我就慢慢熬吧。。。如下是我用執行完後的結果作成的統計圖表(ps:圖表中的數據是我在學院機器上的結果,在本身電腦上時間確定會少量多,就懶得再算一遍了,反正狀況都同樣~~): 數據結構

      結果很明顯,快速排序、堆排序、歸併排序這三種執行效率最快,不過話說回來,冒泡排序的代碼真的是最好寫的!看來算法高效代碼複雜與算法低下代碼簡單是個很辯證的關係啊! :shock: 函數

相關文章
相關標籤/搜索