分析插入与归并排序

插入排序与归并排序算法比较

实验内容:

1、       编写函数分别实现插入排序和归并排序算法

2、       编写主函数通过调用函数实现对待排数据的调用

3、       待排数据利用随机函数循环产生10万个以上的数据

4、       利用求系统时间的函数,分别求出2个排序函数调用前和调用后的时间,计算出插入排序运行时间和归并排序的运行时间

5、       算法的比较:

(1) 相同待排序数据下,插入排序和归并排序算法的运行时间比较;

(2) 同一种排序算法下最好的情况,一般情况,最坏的情况运行时间比较

函数分析:

(1) 插入排序

基本思想:将一个数插入有序数列,插入后仍然有序。

设计原理:1.给出一个无序数列,先取出一个数(一个数自然是一个有序数列);

2.再取下一个数,往之前取出的数进行排序,直到找到合适的位置为止(需要一层内循环);

3.继续按第二步操作,直到取到数列最后一位为止(进行一层外循环);

时间复杂度:O(n^2)

代码:

void insert(int n,int a[]){

int j,i,key;

for(i=1;i<n;i++){          //外层循环

key=a[i];

j=i-1;

     while(j>=0&&a[i]<a[j]){   //内层循环

       a[j+1]=a[j];

       j--;

}

a[j+1]=key;

}

}

(2)           归并排序

递归:不撞南墙不回头。(自己理解)

基本思想:将无序序列分成大致相等的两部分。再对两部分进行递归排序,再将两个有序部分并归成一个有序序列。

设计原理:(分治策略)

分解+合并(两个函数)

1.   将一个大序列的排序问题分解为对两个或多个子序列的排序问题

2.   然后对子序列递归使用同样的方发进行排序

3.   在子序列排好后,将结果合并起来

时间复杂度:O(nlogn)

代码:

编写合并函数void merge(int ,int ,int ,int,),易陷的误区。

1.    容易新建数组C的计数值i设为0,如果放在函数内,将犯一个大错误。如果做全局变量也不太方便。最好是将start赋值给i,因为每次函数时给从start到end之间的数进行排序,所以在函数内给i赋值start是最清晰的。

2.    注意数组a,应该清楚的知道是给数组a排序,目标是在数组a的基础上排序。所以应该将每次排好序赋给数组c的值在重新赋给数组a,否则将起不到在每次分解后再合并的作用,最后结果只是给n/2的两半无序部分排序。结果错误。

3.    合并设计思路:一:在两半部分都存在数的时候,比较大小,小的先赋值给数组c;重复操做;

直到其中一部分为空。

二:如果有一部分为空,将其余有序数组直接插到c数组后面。

void merge(int a[],int start,int mid,intend){//合并

  intj,k,p;

  j=start;k=mid+1;

  p=start;

  while(p<=end){

         if((j<=mid)&&(k<=end))

         {

                if(a[j]<a[k])

                {

                       c[p]=a[j];j++;

                       p++;

                }

                else

                {

                       c[p]=a[k];k++;

                       p++;

                }

         }

         elseif(j>mid)

         {

                for(;k<=end;k++)

                {

                       c[p]=a[k];

                       p++;

                }

         }

         elseif(k>end)

 

                for(;j<=mid;j++)

                {

                       c[p]=a[j];

                       p++;

                }

  }

  for(inti=start;i<=end;i++)

         a[i]=c[i];

}

分解函数void merge_sort(int ,int ,int,)中的难题;了解到递归函数的两次调用递归的过程,抽象的去理解;这样会更好的理解下面的代码;

 

void merge_sort(int a[],int start,intend){      //分治法

  intmid;

  mid=(start+end)/2;

  if(end>start){

         merge_sort(a,start,mid);

      merge_sort(a,mid+1,end);

         merge(a,start,mid,end);

  }

  else

  return;

}

(3)rand()与srand()

rand()是随机数发生器,所在头文件:stdlib.h,用法:int rand(void);

函数说明:

         rand()的内部实现是用线性同余法做的,它不是真的随机数,因为周期特别长,所以在一定的范围内可以看成随机的。

         rand()返回一随机数值的范围在0至rand_max之间。0~rand_max每个数字被选中的几率是相同的。

         用户未设定随机数种子,系统默认的随机数种子为1.

         rand()产生的是伪随机数字,每次执行时相同;若要不同,用srand()初始化它。

         srand()是初始化随机数的发生器;所在头文件stdlib.h;用法:void srand(unsigned int seed);

         函数说明:

         srand()用来你设置rand()产生随机数时的随机数种子 ;

        参数seed必须是个整数,通常可以利用time(0)

返回值或NULL来当做seed;用time函数值(即当前时间),因为两次调用rand的时间通常是不同的,这样就可以保证种子的随机性。

        如果每次seed都设相同值,rand()所产生的随机数

值每次就会一样。

rand()与srand()关系

rand()和srand()要一起使用,其中srand()用来初始

化随机数种子,rand()用来产生随机数。

算法的对比:

归并排序的时间复杂度:nlogn;

插入排序的时间复杂度:n^2;

程序:

#include<stdio.h>

#include<stdlib.h>

#include<time.h>

int c[100001]={0};

int s[100001]={0},s1[100001]={0};

void insort(int n,int b[])

{

    int j,i,key;

   for(i=1;i<n;i++)//外层循环

       {

       key=b[i];

        j=i-1;

       while(j>=0&&key<b[j])//内层循环

              {    

           b[j+1]=b[j];

            j--;

              }

       b[j+1]=key;

       }

}

void merge(int a[],int start,int mid,int end){

       int j,k,p;

       j=start;k=mid+1;

       p=start;

       while(p<=end){

              if((j<=mid)&&(k<=end))

              {

                     if(a[j]<a[k])

                     {

                            c[p]=a[j];j++;

                            p++;

                     }

                     else

                     {

                            c[p]=a[k];k++;

                            p++;

                     }

              }

              elseif(j>mid)

              {

                     for(;k<=end;k++)

                     {

                            c[p]=a[k];

                            p++;

                     }

              }

elseif(k>end)

                     for(;j<=mid;j++)

                     {

                            c[p]=a[j];

p++;

                     }

       }

       for(inti=start;i<=end;i++)

              a[i]=c[i];

}

void merge_sort(int a[],int start,int end){      //分治法

       int mid;

       mid=(start+end)/2;

       if(end>start){

              merge_sort(a,start,mid);

           merge_sort(a,mid+1,end);

              merge(a,start,mid,end);

       }

       else

       return;

}

int main(){

       inti,n,n1,a[100001]={0},b[100001]={0};

       double t;

       time_tc_beg,c_end,end;

       printf("输入要排的个数:\n");

       scanf("%d",&n);

       n1=n-1;

       srand((unsigned)time(NULL));   //产生随机种子

       for(i=0;i<n;i++)   //产生随机数

       {

              a[i]=rand()%1000000;

              b[i]=a[i];

           printf("%d ",a[i]);

       }

       printf("\n\n");

       c_beg=clock();

       merge_sort(a,0,n-1);

              c_end=clock();

       t=(double)(c_end-c_beg)*1000/CLOCKS_PER_SEC;

 

       printf("\n一般情况\n");

       printf("归并排序所花费的时间:%f 毫秒\n",t);

    insort(n,b);

       end=clock();

       t=(double)(end-c_end)*1000/CLOCKS_PER_SEC;

       printf("插入排序花费的时间:%f 毫秒\n",t);

       printf("\n最好情况\n");

       c_beg=clock();

       merge_sort(a,0,n-1);

              c_end=clock();

       t=(double)(c_end-c_beg)*1000/CLOCKS_PER_SEC;

       printf("归并排序所花费的时间:%f 毫秒\n",t);

    insort(n,b);

       end=clock();

       t=(double)(end-c_end)*1000/CLOCKS_PER_SEC;

       printf("插入排序花费的时间:%f 毫秒\n",t);

       printf("%d\n",n);

   printf("\n最坏情况\n");    

       for(i=0;i<n;i++)

       {

              s[i]=a[n1];

              s1[i]=a[n1--];

       }

 

       c_beg=clock();

       merge_sort(s,0,n-1);

              c_end=clock();

       t=(double)(c_end-c_beg)*1000/CLOCKS_PER_SEC;

       printf("归并排序所花费的时间:%f 毫秒\n",t);

   insort(n,s1);

       end=clock();

       t=(double)(end-c_end)*1000/CLOCKS_PER_SEC;

       printf("插入排序花费的时间:%f 毫秒\n",t);

       return 0;

}

 

 

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值