搜集一些有趣的排序算法,持续更新

给一个n大小的数据进行排序,我们可以选择许多排序方法。各有优劣。

判断你一个算法的好坏。可以从他的比较次数和移动次数来划分。

排序需要的平均比较次数,最快比较速度和最慢比较速度,需要额外的空间已经稳定性。

比较速度取决于排好一次序需要比较几次。

稳定性是指当二个数是相同的时候,如果你不改变他的前后关系,则是稳定。改变了则不稳定。

下面是我搜集的一些算法。(从小到大排,处理很大的数据)

一:冒泡排序

平均比较次数:n*n

最少比较次数:n

最多比较次数:n*n

需要的额外空间:0

稳定性:稳定

方法,从头开始,二二比较,若右边小于左边则二者互换位,一轮下来最右边为最大数,第二轮得到第二大的数;设置标准位,如果一轮下来没有发生移位则排序结束;

int Bubble(int array[],int size)  //传入数组首地址和大小,返回值是比较次数
{
    int i,j,k,n=0;
    for(i=0;i<size-1;i++)    //i=0则得到最大的数,i=1得到第二大的数,最差的情况下需要的得到n-1大的数才能完成排序     
    { 
        k=0;         //标志位
        for(j=0;j<size-1-i;j++)   //排序获得前n-i-1中最大的数
        {
            n++;        //比较次数
            if(array[j]>array[j+1])
            {   
                int tem=array[j];
                array[j]=array[j+1];
                array[j+1]=tem;
                k++;
            }
         }
         if(0==k)        //未发生移位代表排序完成
            return n;
     }
     return n;
}
冒泡排序示意图:

二:鸡尾酒排序

平均比较次数:n*n

最少比较次数:n

最多比较次数:n*n

需要的额外空间:0

稳定性:稳定

方法:从头开始,俩俩比较找到最大数,当比较到末尾时,从末尾开始俩俩比较找到最小数,左右循环;当一次循环中没有发生位移则表示排序结束

        void Exchange(int array[],int sub) //交换函数,传入一个数组和下标,领该下标下的成员与右成员交换数值
     25 {
     26     int tem=array[sub];
     27     array[sub]=array[sub+1];
     28     array[sub+1]=tem;
     29 }
     30 int Cocktail(int array[],int size)  //传入一个数组和数组大小,令数组进行鸡尾酒排序
     31 {
     32     int i,j,k=0,n=0;     //k是标志位,n是计算比较次数当作返回值
     33     for(i=0;i<size/2;i++)    //最多比较size-1次,一个循环比较二次,所以除以二
     34     {
     35         k=0;
     36         for(j=n/2;j<size-1-n/2;j++)  //右循环
     37             if(array[j]>array[j+1])
     38             {
     39                k++;
     40                Exchange(array,j);
     41             }
     42         n++;
     43         if(0==k)              //k==0代表排序完成
     44             return size*n+n*(n-1)/2;   //等差数列,返回的是比较次数
     45         k=0;
     46         for(j=j-1;j>=0+i;j--)     //左循环
     47             if(array[j]>array[j+1])
     48             {
     49                 k++;
     50                 Exchange(array,j);
     51             }
     52         n++;
     53         if(0==k)
     54             return size*n+n*(n-1)/2;
     55     }
     56     return size*n+n*(n-1)/2;
     57 }

鸡尾酒排序示意图


三 :选择排序

平均比较次数 n*n

最少比较次数 n*n

最多比较次数 n*n

需要额外的空间 0

稳定性 不稳定

方法:循环一次取一个最小值然后与第一个值进行交换,长度减一,继续循环,共循环n-1次即可排序完全;

int choice(int array[],int size)
     59 {
     60     int i,j,n=0,min,tem;
     61     for(i=0;i<size-1;i++)  //取n-1次最小数
     62     {
     63         min=i;
     64         for(j=i;j<size;j++)  //找到最小数 
     65         {   
     66             n++;
     67             if(array[min]>array[j])
     68                 min=j;
     69         }
     70         tem=array[i];
     71         array[i]=array[min];
     72         array[min]=tem;
     73     }
     74     return n;   //返回比较的次数
     75 }

选择排序示意图

四 插入排序

平均比较次数 n*n

最少比较次数 n

最多比较次数 n*n

需要额外的空间 0

稳定性 稳定

方法 数组第一个已排好序,后一个数组成员若小于前一个则互换,直到该数组碰到小于它本身的数或者到头;

        int insertion(int array[],int size)
     77 {
     78     int i,j,tem,n=0;  //n计算比较次数,
     79     for(i=1;i<size;i++)  //默认第一个是已经排好序
     80     {
     81         j=i;
     82         tem=array[j];
     83         while(tem<array[j-1] && j!=0)  //如果该数小于前一个数或还没到头则前移
     84         {
     85             array[j]=array[j-1];  
     86             j--;
     87             n++;
     88         }
     89         n++;
     90         array[j]=tem;
     91     }
     92     return n;  /返回比较次数
     93 } 
示意图



五  二分插入

平均比较次数 n*n

最少比较次数 nlogn

最多比较次数 n*n

所需额外空间 0

稳定性 稳定

方法:从第二个数开始排序,之前的数已经排好序,用二分法查找中间的数与中间的数大小关系,知道找到该数应该排得位置并插入

     94 int Binaryinsertion(int array[],int size)
     95 {
     96     int i,n=0,left,right,tem;
     97     for(i=1;i<size;i++)  //i之前的数已经排好序
     98     {
     99         right=i;
    100         left=0;
    101         while(left<right)  //最终lef所在的位置为该数的位置
    102         {
    103             if(array[(right+left)/2]<=array[i])
    104                 left=(right+left)/2+1;
    105             else
    106                 right=(right+left)/2-1;
    107             n++;
    108         }   
    109         tem=array[i];
    110         right=i;
    111         while(right!=left)//left所在位置总体往前挪一格
    112         {   
    113             array[right]=array[right-1];
    114             right--;
    115         }
    116         array[left]=tem;//插入
    117     }
    118     return n;//返回比较次数
    119 }  
示意图

 

六 希尔排序

平均比较次数 nlogn~n*n

最少比较次数 n^1.3

最多比较次数 n*n

需要额外的空间 0

稳定性 不稳定

方法:每隔d个进行排序,当d等于3时,则数组第一个和第四个和(1+3d)n排序。排好之后d减少,直到d为1;d目前为止没有最佳;

        int Hill(int array[],int size)    //输入数组和数组大小
    121 {
    122     int i,j,tem,n=0,d;     //d为步长,该函数步长依次为size/2,size/2/2,...1;
    123     for(d=size/2;d>0;d/=2)  
    124         for(i=d;i<size;i++)  //对同一步长的数进行插入排序
    125             for(j=i,n++;array[j]<array[j-1] && j>=d;j-=d)
    126             {   
    127                tem=array[j];
    128                array[j]=array[j-1];
    129                array[j-1]=tem;
    130                n++;
    131             }
    132     return n;
    133 }
    134

示意图

七  归并排序

平均运算次数 nlogn

最多运算次数 nlogn

最少运算次数 nlogn

需要额外的空间 0

稳定性 稳定

方法:将一个size大小的数组先分为size/2个,每个组里有2个成员,将其排序。再分成四个一组进行排序,直到一组里的成员大于size个

    134 int Merger(int array[],int size)   //输入数组和数组大小
    135 {
    136     int i,j,right,left,n=0,tem;  
    137     for(i=2;i<size*2;i*=2)       //先2个归并,依次乘二
    138         for(j=0;j+1<size;j+=i)   //j代表一个组
    139              for(left=j,right=j+i/2;right<size && right<j+i && left!=j+i/2;) //j组里前i/2个和后i/2个已经排好序,将他俩合并;
    140              {
    141                   if(array[right]<array[left])
    142                   {   
    143                       tem=array[right];
    144                       array[right]=array[left];
    145                       array[left]=tem;
    146                       left++;   
    147                       right++;
    148                   }
    149                   else
    150                       left++;
    151                  n++;
    152              }   
    153      return n;   //返回比较次数
    154 }    
    155    
示意图


八 堆排序

平均比较次数 nlogn

最多比较次数 nlogn

最少比较次数 nlogn

需要额外的空间 0

稳定性 不稳定

方法:将数组以二叉树进行排序,父节点大于二个子节点,每次排好序后,将根节点与最右边的叶节点交换,数组长度减一。

    134 int n=0;   //全局变量,计算比较次数
    135 int two(int array[],int size,int ia)  //输入数组,数组大小和已排好序的个数
    136 {
    137     int i=ia,j,tem,k=0,left;
    138     for(j=1;j<size-i;j++)    //j为父节点
    139     {
    140         for(left=j*2;left<j*2+2;left++)  //j*2和j*2+1为j的二个子节点
    141         {
    142             n+=2;  //比较了二次
    143             if(left<=size-i && array[left-1]>array[j-1] )  //如果子节点大于父节点,二者交换
    144             {
    145                 tem=array[left-1];
    146                 array[left-1]=array[j-1];
    147                 array[j-1]=tem;
    148                 k++;
    149              }
    150          }
    151       }
    152       return k;
    153 }
    154 int Heapsort(int array[],int size)  //输入数组和数组大小
    155 {
    156     int i=0,tem,k=1;
    157     while(k!=0)   //使数组进行二叉树初始化
    158         k=two(array,size,0);
    159     for(i=0;i<size-1;i++)   //将根提取出来
    160     {
    161          two(array,size,i);
    162          tem=array[0];
    163          array[0]=array[size-1-i];
    164          array[size-1-i]=tem;
    165     }
    166     return n;  //返回比较次数
    167 }
示意图


九 快速排序

平均比较次数 nlogn

最少比较次数 nlogn

最多比较次数 n*n

需要的额外空间

稳定性 不稳定

方法:在数组里找个数当作标杆,然后与其他成员进行比较大于它的放右边,小于它的放左边。然后在它的左边和右边继续找个标杆,直到排好序

    191 int n=0;   //全局变量用来计算比较次数
    192 int quick(int array[],int right,int left)  //输入数组,数组的最左边的下标,数组的最右边下标  
    193 {   
    194     if(right<=left)
    195         return n;  //返回比较次数
    196     int head=left,tail=left+1,now,tem;  //以第一个数组成员做标杆与其他成员作比较,tail指向其他成员
    197     while(tail<=right)//tail值为head+1到right
    198     {
    199         n++;     //比较次数加一
    200         if(array[tail]<array[head])  //如果成员比标杆小,则移到他左边
    201         {   
    202             now=tail;
    203             tem=array[tail];
    204             while(now!=head)
    205             {
    206                 array[now]=array[now-1];
    207                 now--;
    208             }
    209             array[head]=tem;
    210             head++;  //head下标加1
    211             tail++;   //tail下标加一
    212             continue;
    213          }
    214          tail++;
    215      }
    216      quick(array,head-1,left);  //将标杆左边的组进行排序
    217      quick(array,right,head+1);  //将标杆右边的组进行排序
    218 }  

示意图





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

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值