1. 程式人生 > >C語言排序(五)——插入排序與歸併排序演算法比較

C語言排序(五)——插入排序與歸併排序演算法比較

一.實驗內容:

1、         編寫函式分別實現插入排序和歸併排序演算法

2、         編寫主函式通過呼叫函式實現對待排資料的呼叫

3、         待排資料利用隨機函式迴圈產生10萬個以上的資料

4、         利用求系統時間的函式,分別求出2個排序函式呼叫前和呼叫後的時間,計算出插入排序執行時間和歸併排序的執行時間

5、         演算法的比較:

(1)                      相同待排序資料下,插入排序和歸併排序演算法的執行時間比較;

(2)                      同一種排序演算法下最好的情況,一般情況,最壞的情況執行時間比較

 插入排序:插入即表示將一個新的資料插入到一個有序陣列中,並繼續保持有序。例如有一個長度為N的無序陣列,進行N-1次的插入即能完成排序;第一次,陣列第1個數認為是有序的陣列,將陣列第二個元素插入僅有1個有序的陣列中;第二次,陣列前兩個元素組成有序的陣列,將陣列第三個元素插入由兩個元素構成的有序陣列中......第N-1次,陣列前N-1個元素組成有序的陣列,將陣列的第N個元素插入由N-1個元素構成的有序陣列中,則完成了整個插入排序。

以下面5個無序的資料為例:

65 27 59 64 58 (文中僅細化了第四次插入過程)

第1次插入: 27 65 59 6458

第2次插入: 27 59 65 6458

第3次插入: 27 59 64 6558

第4次插入: 27 58 59 6465

 

二.演算法分析

三.實驗程式碼
#include<stdio.h>
#include<stdlib.h>//數學
#include<time.h>//時間

void insertSort(long int *, long int); //定義插入排序函式
void merge(long int X[], long int Z[], long int s, long int u, long int v);  
void mergePass(long int X[], long int Y[],long  int n, long int t);
void mergeSort(long int X[],long  int n);  
void insertSort(long int *array,long int len)  
{  
    long int i,j,temp;  
  
    for(i=1;i<len;i++)  //從第二個元素開始
    {  
        temp=array[i]; //取出代插元素 
        for(j=i-1;j>=0;j--) //帶插元素依次和前一個比較,將較大數依次後移 
        {  
            if(array[j]>temp)  
            {  
                array[j+1]=array[j];      
            }else  
            {  
                break;  
            }  
        }  
        array[j+1] = temp;  
    }  
}  


//將有序的X[s..u]和X[u+1..v]歸併為有序的Z[s..v]  
void merge(long int X[],long  int Z[], long int s, long int u, long int v)  
{  
   long int i, j, q;  
    i = s;  
    j = u + 1;  
    q = s;  
  
    while( i <= u && j<= v )  
    {  
        if( X[i] <= X[j] )  
            Z[q++] = X[i++];  
        else  
            Z[q++] = X[j++];  
    }  
  
    while( i <= u )   //將X中剩餘元素X[i..u]複製到Z  
        Z[q++] = X[i++];  
    while( j <= v )   //將X中剩餘元素X[j..v]複製到Z  
        Z[q++] = X[j++];  
}  
  
/* X[0..n-1]表示參加排序的初始序列 
 * t為某一趟歸併時子序列的長度 
 * 整型變數i指出當前歸併的兩個子序列中第1個子序列的第1個元素的位置 
 * Y[0..n-1]表示這一趟歸併後的結果 
*/  
void mergePass(long int X[], long int Y[], long int n,long int t)  
{  
    int i = 0, j;  
    while( n - i >= 2 * t )     //將相鄰的兩個長度為t的各自有序的子序列合併成一個長度為2t的子序列  
    {  
        merge(X, Y, i, i + t - 1, i + 2 * t - 1);  
        i = i + 2 * t;  
    }  
  
    if( n - i > t )       //若最後剩下的元素個數大於一個子序列的長度t時  
        merge(X, Y, i, i + t - 1, n - 1);  
    else             //n-i <= t時,相當於只是把X[i..n-1]序列中的資料賦值給Y[i..n-1]  
        for( j = i ; j < n ; ++j )  
            Y[j] = X[j];  
}  
  
void mergeSort(long int X[],long int n)  
{  
   long int t = 1;  
   long int *Y = (long int *)malloc(sizeof(long int) * n);  
    while( t < n )  
    {  
        mergePass(X, Y, n, t);  
        t *= 2;  
        mergePass(Y, X, n, t);  
        t *= 2;  
    }  
    free(Y);  
}  
  
void print_array(long int array[],long int n)  
{  
   long int i;  
    for( i = 0 ; i < n ; ++i )  
        printf("%d ", array[i]);  
    printf("\n");  
}  
  


 
int main()
{
	printf("請輸入要產生的隨機數個數:");
	double  start, finish;
	long int a[100005],b[100005],c[100005],d[100005],n,i;
   
    scanf("%d",&n);
 for(i=0;i<n;i++)
 {
   a[i]=b[i]=rand()%10000+1;  //產生隨機數 

   //printf("%d ",b[i]);
 }
    start=clock();//取開始時間
    insertSort(a, n);  
	finish = clock();//取結束時間
	printf("採用插入排序的時間:");
	printf( "%f 毫秒\n",(finish-start)/CLOCKS_PER_SEC*1000);//以秒為單位顯示之


  // for(i=0;i<n;i++)  
    //    {  
      //      printf("%d ",a[i]);  
        //}  

        start=clock();//取開始時間
        mergeSort(b,n);
	//	print_array(b,n);
		finish = clock();//取結束時間
		printf("採用歸併排序的時間:");
	printf( "%f 毫秒\n",(finish-start)/CLOCKS_PER_SEC*1000);//以秒為單位顯示之
   /* for(i=0; i<n; i++)
        printf("%d ", a[i]);*/
    printf("\n");
   printf("%d個數插入排序最好結果用時:",n);
    start=clock();//取開始時間
    for(i=0;i<100000;i++)
	{
		c[i]=i;
	}
	insertSort(c,i-1); 
	finish = clock();//取結束時間
	printf( "%f 毫秒\n",(finish-start)/CLOCKS_PER_SEC*1000);
	/////////////////////////////////////////
	/*
	for(i=0;i<100;i++)
	{
		printf("%d ",c[i]);
	}
	printf("\n\n\n\n\n");
	*/ 
	//////////////////////////////////////////
	
	 printf("%d個數插入排序最壞結果用時:",n);
    start=clock();//取開始時間
    for(i=99999;i>=0;i--)
	{
		d[i]=99999-i;
	}
	insertSort(d,n);

	finish = clock();//取結束時間
	printf( "\n%f 毫秒\n",(finish-start)/CLOCKS_PER_SEC*1000);
	
	/////////////////////////////////////////
	/*
	for(i=0;i<100;i++)
	{
		printf("%d ",c[i]);
	}
	printf("\n\n\n\n\n");
	*/ 
	//////////////////////////////////////////
	
	printf("%d個數歸併排序最好結果用時:",n);
	start=clock();//取開始時間
	for(i=0;i<n;i++)
	{
		c[i]=i;
	}
	mergeSort(c,n);
	finish = clock();//取結束時間
	printf( "%f 毫秒\n",(finish-start)/CLOCKS_PER_SEC*1000);
	
	   printf("%d個數歸併排序最壞結果用時:",n);
        start=clock();//取開始時間
        for(i=n-1;i>=0;i--)
	{
		d[i]=99999-i;
	}
        mergeSort(d,n);
        /*for(i=0;i<n;i++)
		{
			printf("%d ",d[i]);
		 } */

	finish = clock();//取結束時間
	printf( "\n%f 毫秒\n",(finish-start)/CLOCKS_PER_SEC*1000);
        return 0;
}
  


四.實驗結果




五.實驗分析

  在隨機陣列中,歸併排序明顯優於插入排序,且數值越大越明顯。有序序列結果不明顯,但仍然歸併排序優於插入排序。