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

简介: 直接插入,希尔排序,选择排序

弱化版直接插入

 

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) 因为不管是顺序还是逆序我们都要进行遍历一遍,然后再判断谁是最大的,谁是最小的,所以复杂度会很高


相关文章
|
8月前
|
存储 搜索推荐 算法
[数据结构]————排序总结——插入排序(直接排序和希尔排序)—选择排序(选择排序和堆排序)-交换排序(冒泡排序和快速排序)—归并排序(归并排序)
[数据结构]————排序总结——插入排序(直接排序和希尔排序)—选择排序(选择排序和堆排序)-交换排序(冒泡排序和快速排序)—归并排序(归并排序)
|
存储 搜索推荐 算法
插入排序:简单而有效的排序方法
在计算机科学中,排序算法是一个重要且常见的主题,它们用于对数据进行有序排列。插入排序(Insertion Sort)是其中一个简单但有效的排序算法。本文将详细解释插入排序的原理和步骤,并提供Java语言的实现示例。
391 4
|
7月前
|
算法 数据处理 Python
插入排序、选择排序和二分查找
插入排序、选择排序和二分查找
|
7月前
|
算法 搜索推荐 Java
选择排序就是这么容易
选择排序就是这么容易
41 0
|
7月前
|
搜索推荐
冒泡排序、选择排序、二分查找
冒泡排序、选择排序、二分查找
29 0
|
8月前
|
搜索推荐 测试技术
排序算法-插入/希尔排序
排序算法-插入/希尔排序
29 0
|
存储 搜索推荐 算法
七大排序 (9000字详解直接插入排序,希尔排序,选择排序,堆排序,冒泡排序,快速排序,归并排序)
七大排序 (9000字详解直接插入排序,希尔排序,选择排序,堆排序,冒泡排序,快速排序,归并排序)
98 0
|
算法 搜索推荐 测试技术
【数据结构】带你玩转排序:堆排序、希尔排序、插入排序、选择排序、冒泡排序、快排(多版本)、归并排序
【数据结构】带你玩转排序:堆排序、希尔排序、插入排序、选择排序、冒泡排序、快排(多版本)、归并排序
131 0
|
搜索推荐
冒泡排序,选择排序,直接插入排序
🐰冒泡排序 🐰选择排序 🐰直接插入排序
|
算法 搜索推荐 测试技术
直接选择排序
直接选择排序
118 0
直接选择排序