直接插入,希尔排序,选择排序

 弱化版直接插入

 

void InsertSort(int*a,int n){
    assert(a);
    int end=n-2;
    int x;
    while(end>=0){
        //针对的是原本有顺序的,最后一个和x比,然后加入x后恢复有序
        if(a[end]>x){
            a[end+1]=a[end];
            --end;
        }
         else {
             break;
        }
    }
    a[end+1]=x;
}

原本是有序,插入x来使数组继续有序

//升级一下,假如说是随机数,怎么来给他变成有序。
//我们需要假设有序,也就是第一个数存在时,认为第一个数有序,然后第二个数是插入,然后。。。到最后(n个数组也就是 end最后n-2,和插入的最后一个n-1来比较插入
void InsertSort(int *a,int n)
{  assert(a);
    for(int i=0;i<n-1;i++){
        int end=i;//从头开始默认谁开始就是最后一个,也就是最大的,换句话说无时无刻都在插入的过程
        while(end>=0){
            if(a[end]>x){                         //
                a[end+1]=a[end];                  //最好O(N)有顺序,最坏O(N*N)
                --end;
            }
            else{
                break;
            }
        }
    }

弱化版希尔排序 

gap是分组的意思,也就是分三组,开始只换9和5.把一个大问题慢慢分成小问题

void ShellSort(int*a,int n){                //按gap分组数据进行排,说白了就是预排处理
        int gap=3;
        int end=0;
        int x=a[gap+end];
        while(end>=0){
            if(a[end]>x){
                a[end+gap]=a[end];
                end-=gap;
            }
              else {
                  break;
            }
            a[end+gap]=x;
            }
        }


    }

 假如是分三组,就是将

较弱版希尔排序,简单的排一组

 


    void ShellSort(int*a,int n){                //按gap分组数据进行排,说白了就是预排处理
        int gap=3;
        for(int i=0;i<n-gap;i+=gap)     //加了一个这个,简单排一组的黑线,
        int end=i;
        int x=gap+end;                   //为什么是n-gap看下面
        while(end>=0){
            if(a[end]>x){         
                a[end+gap]=a[end];
                end-=gap;
            }
              else {
                  break;
            }
            a[end+gap]=x;
            }
        }


    }

为什么要在n-gap : 首先i=0;,n-gap就是上面的6,6的前面是倒数第二个黑线,我们是要把下一个视为插入的元素,那么就是要他们在他们这些线的倒数第二个元素之前都可以,但是也同样不能碰到后面的那几个,因为他们彼此是最后一个元素,所以只有n-gap处于刚刚好的位置。

这是排的一组黑线,如果要全排完,看下面

完全版,希尔排序:一组一组的排版

     void ShellSort(int*a,int n){                //按gap分组数据进行排,说白了就是预排处理
        int gap=3;
       
        for(int j=0;j<gap;++j)
        for(int i=j;i<n-gap;i+=gap)
            int end=i;
        int x=gap+end;
        while(end>=0){
            if(a[end]>x){
                a[end+gap]=a[end];
                end-=gap;
            }
              else {
                  break;
            }
            a[end+gap]=x;
            }
        }


    }

多组一起排版

 void ShellSort(int*a,int n){                //按gap分组数据进行排,说白了就是预排处理
        int gap=3;
       
        for(int i=0;i<n-gap;++i){
            int end=i;
        int x=gap+end;
        while(end>=0){
            if(a[end]>x){
                a[end+gap]=a[end];
                end-=gap;
            }
              else {
                  break;
            }
            a[end+gap]=x;
            }
        }


    }

多组一起排:也就是将9和5先换,然后1和7.。,都给他排一遍

            希尔排序,也就是预排序可以进行多次,

            因此诞生了 多组预排序➕直接插入(gap==1)假如gap ==1希尔排序就会变成直接插入排序

void ShellSort(int*a,int n){                //按gap分组数据进行排,说白了就是预排处理
        int gap=n;
        while(gap>1){
            gap/=2
        //或者gap=gap/3+1
        for(int i=0;i<n-gap;++i){
            int end=i;
        int x=gap+end;
        while(end>=0){
            if(a[end]>x){
                a[end+gap]=a[end];
                end-=gap;
            }
              else {
                  break;
            }
            a[end+gap]=x;
            }
        }


    }

gap无论是上面的除二还是除3最后都必须保证有一个个数是一个一,所以是看N来进行选择gap 到底要选择什么。

所以最好的是O(n)自然有顺序

        最坏是换组拿最大的换也就是 (1+2+……+到N/gap)*gap 算是拿那个一组一组的gap分的

将gap带入N/2 最后时间复杂度差不多是N*logN

        选择排序​​​​​​​

 void Swap(int*ps,int*py){
        int tmp=*ps;
        *ps=*py;
        *py=tmp
    }
    void SelectSort(int*a,int n){
        int begin=0;
        int end=n-i;
        while(begin<end){                 //奇数的话会自己相等,偶数的话会自己错开
            int mini=begin;              //随便给个值,但不可以不给,不能选值而是选择下标
            int maxi=begin;
                if(a[i]<a[mini]){
                    mini=i;
                }
                if(a[i]>a[maxi]){
                    maxi=i;
                }//找最大和最小下标
                Swap(&a[begin],&a[mini]);
                if(begin==maxi){        //这一步很重要,具体下面具体阐述
                    maxi=mini;
                }
                Swap(&a[end],&a[maxi]);
                ++begin;
                --end;
            }
        }
        

选择排序,先找最大和最小的,两个两个来,然后两个次大的和次小的。。。一直一直直到彼此错开。

如果没有注释的那行代码,会导致最大的和begin在一个位置,这样1和begin换位置的同时,最大的位置26改变,但是maxi的位置却没有改变,导致,maxi位置在交换的时候会出现错误。

      选择排序的缺点就是时间复杂度O(N^2) 因为不管是顺序还是逆序我们都要进行遍历一遍,然后再判断谁是最大的,谁是最小的,所以复杂度会很高

  • 7
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 5
    评论
评论 5
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

狗哥不是甜妹

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值