美文网首页数据结构与算法
算法(一)之排序算法(四)——希尔排序(ShellSort)

算法(一)之排序算法(四)——希尔排序(ShellSort)

作者: bryanrady_wang | 来源:发表于2017-12-20 15:55 被阅读11次

    希尔排序也是八大排序算法之一,它是在插入排序的基础上演变而来的,也称缩小增量排序,是直接插入排序
    算法的一种更高效的改进版本。希尔排序是非稳定排序算法。其排序原理是:

    将无序数组分割为若干个子序列,子序列不是逐段分割的,而是相隔特定的步长的子序列,对各个子序列进行插入排序;然后再选择一个更小的步长,再将数组分割为多个子序列进行排序......最后选择步长为1,即使用直接插入排序,使最终数组成为有序。

    如现在有一组数据:[3, 1, 8, 6, 2, 5, 9, 4, 7]

    使用希尔排序对这组数据进行排序,具体流程:

    第一趟排序:选择步长为4

            3    1    8    6    2    5    9    4    7
            
            选择步长为4,那么:
                 [3, 2, 7]构成了一个子序列,这个子序列的排序结果为[2,3,7];
                 [1, 5]构成了一个子序列,这个子序列的排序结果为[1, 5];
                 [8, 9]构成了一个子序列,这个子序列的排序结果为[8, 9];
                 [6, 4]构成了一个子序列,这个子序列的排序结果为[4, 6];
                   
            所以第一趟的排序结果为:
    
             2    1    8    4    3    5    9    6    7
    

    第二趟排序:选择步长为2

             2    1    8    4    3    5    9    6    7
    
            选择步长为2,那么:
                 [2, 8,  3, 9, 7]构成了一个子序列,这个子序列的排序结果为[2, 3, 7, 8, 9];
                 [1, 4, 5, 6]构成了一个子序列,这个子序列的排序结果为[1, 4, 5, 6];
                 后面从8开始的和第一个子序列一样,就不用继续分了。
    
            所以第二趟的排序结果为:
    
             2    1    3    4    7    5    8    6    9
    
        这样一看我们就十分接近排序结果了。
    

    第三趟排序:选择步长为1

            2    1    3    4    7    5    8    6    9
    
              选择步长为1,就是对这组数据进行直接插入排序,所以最后就可以得出排序结构。
    
            1    2    3    4    5    6    7    8    9
    

    还有疑问的话现在上图,看能否帮助我们更好的理解。

    已知的最好步长序列由Marcin Ciura设计(1,4,10,23,57,132,301,701,1750,…) 这项研究也表明“比较在希尔排序中是最主要的操作,而不是交换”。用这样步长序列的希尔排序比插入排序和堆排序都要快,甚至在小数组中比快速排序还快,但是在涉及大量数据时希尔排序还是比快速排序慢。

    希尔排序的代码就是根据直接插入排序来改就行了,特别记住当我们的步长为1时,就是调用的直接插入排序。说了这么多,就算原理理解了我们最终还是要会写代码才行:

        public static void shellSort(int[] array,int step){
            for(int k=0; k<step; k++){  //对步长的定位,选择每次操作的开始位置
                for(int i=k+step;i<array.length;i=i+step){
                    int j=i;
                    int target = array[i];
                    while(j>step-1 && target<array[j-step]){
                        array[j] = array[j-step];
                        j = j-step;
                    }
                    array[j] = target;
                }
            }
        }
    

    当我们使用希尔排序的时候,就根据步长多调用几次这个方法就行了,一般最多3次就够用了。

    希尔排序的应用场景:当我么每做一次操作数据就需要排序一次的,这种情况用希尔排序效率最高,就像QQ游戏里的打麻将,摸一张打一张这种场景。

    相关文章

      网友评论

        本文标题:算法(一)之排序算法(四)——希尔排序(ShellSort)

        本文链接:https://www.haomeiwen.com/subject/ywpgwxtx.html