希尔排序

一、原理

       ☆思想:插入排序在记录数较少或序列基本有序时效率高,为了满足这些条件,希尔排序对插入排序做了改进;对序列按一定间隔分组,在每组内进行插入排序,不断缩小间隔直到1,即对整个序列进行插入排序,最终得到有序序列;

       ☆过程:以递增为例,用数组表示,长度为n,整个数组为无序集合;间隔选择方法很多,不一而论,一般为二分、三分等;以初始间隔二分为例,每组最多三个元素,基本是两个元素,如有11个元素,初始间隔为11/2=5,可分为五组,分别为{1,6,11}、{2,7}、{3,8}、{4,9}、{5,10},对每组进行插入排序;缩小间隔为5/2=2,可分为两组,分别为{1,3,5,7,9,11}、{2,4,6,8,10},对每组进行插入排序;缩小间隔为2/2=1,对应整个序列,进行插入排序,排序结束;

二、实现代码

       方法一:JavaScript 代码常规实现,层次清晰,容易理解;对分组进行插入排序时,每次把本组所有元素排序完成,再进行下一组排序;

function ShellSort(arr) {
    var len = arr.length;
    var step = Math.floor(len / 2);
    var curr, preIndex;
    while (step >= 1) {
        //固定步长,所有分组首元素
        for (var i = 0; i < step; i++) {
            //对某分组进行插入排序
            for (var j = i + step; j < len; j += step) {
                curr = arr[j];
                for (var preIndex = j - step; curr < arr[preIndex] && preIndex >= 0;preIndex -= step) {
                    arr[preIndex + step] = arr[preIndex];
                }
                arr[preIndex + step] = curr;
            }
        }
        //步长折半递减
        step = Math.floor(step / 2);
        console.log('' + arr)
    }
}

       方法二:JavaScript 代码简化实现,少一层循环,代码简洁;进行插入排序时,从第一组第二个元素开始,每次插入一个元素,具体过程为插入第一组第二个元素、插入第二组第二个元素、插入第三组第二个元素、…直到最后一个元素,交替插入不同组元素;

function ShellSort(arr) {
    var length = arr.length,
    gap = Math.floor(length / 2),
    temp;

    while (gap > 0) {
        //从每组第二个元素开始插入排序
        for (var i = gap; i < length; i++) {
            temp = arr[i];
            for (var j = i - gap; j >= 0 && arr[j] > temp; j -= gap) {
                arr[j + gap] = arr[j];
            }
            arr[j + gap] = temp;
        }
        console.log(gap + ':' + arr);
        gap = Math.floor(gap / 2);
    }
    return arr;
}

 

三、优化

      无;

四、复杂度

名称 时间复杂度 空间复杂度  稳定性 
平均 最坏 最优
希尔排序 O(n^1.3) O(n²) O(nlogn)  O(1)

X

      最差情况,数组反序,间隔n/2,需要进行n/2 *1次比较,间隔n/4,需要进行n/4 *(1+2+3)次比较,间隔n/8,需要进行n/8 *(1+2+...+7)次比较,…间隔1,需要进行1 *(1+2+3+……+(n-1))=n(n-1)/2次比较,即每个间隔需要(div-1)*n/2次比较,div为2^1、2^2、2^3…,共需要n/2+3n/2+7n/2+...+(n-1)n/2次比较;

      最优情况,数组正序,间隔n/2,需要进行n/2次比较,间隔n/4,需要进行n/4 *3次比较,间隔n/8,需要进行n/8 *7次比较,…间隔1,需要进行(n-1)次比较,即每个间隔需要(div-1)*n/div次比较,div为2^1、2^2、2^3…,共需要n/2+3n/4+7n/8+...+(n-1)≈nlogn次比较;

      本排序需要申请一个额外空间;

      使用数组表示,相同元素顺序可能变化,本排序不稳定。

posted @ 2019-11-23 18:06  老余的水壶  阅读(237)  评论(0)    收藏  举报