高级排序算法之希尔排序

Posted alonwang

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了高级排序算法之希尔排序相关的知识,希望对你有一定的参考价值。

前言

希尔排序是对插入排序的改进,引入维基百科的说明:

希尔排序是基于插入排序的以下两点性质而提出改进方法的:

  1. 插入排序在对几乎已经排好序的数据操作时,效率高,即可以达到线性排序的效率

  2. 但插入排序一般来说是低效的,因为插入排序每次只能将数据移动一位

原文链接希尔排序,本文将介绍希尔排序的实现思路,时间复杂度,稳定性等.

正文

希尔排序

主要思路

要改进插入排序,就要解决"插入排序每次只能将数据移动一位",并且利用"插入排序在几乎已经排好序的数据操作时,效率高"的特性.逻辑描述如下

1. 初始时将数组划分为subArrsNum=arr.length/2个子数组
2. 对这些子数组subArrs使用插入排序排序
3. subArrsNum缩减为一半,缩减后如果subArrsNum>=1,跳转到2,否则 结束.

subArrs的定义如下

subArrs[i]={arr[i],arr[i+k],arr[i+2k],...arr[i+nk]} i<k,arr.length/2 >= k >=1

这里的难点在于对逻辑子数组的理解,下面结合subArrs的定义,举例说明

arr={1,4,6,5,2,7,3,8}

初始时subArrsNum = arr.length/2=8/2=4,四个子数组分别为

subArrs[0]={1,2}={arr[0],arr[0+4]}
subArrs[1]={4,7}={arr[1],arr[1+4]}
subArrs[2]={6,3}={arr[2],arr[2+4]}
subArrs[3]={5,8}={arr[3],arr[3+4]}

如果我们想遍历某个子数组,跨度应该等同于subArrsNum而非1.达成"每次可以将数据移动不止一位"的效果",

而随着子数组数量越来越少,数组也越来越有序,更好的利用"插入排序在几乎已经排好序的数据操作时,效率高"这个特性,代码如下

    public void sort(Comparable[] arr) {
        if (arr.length <= 1) {
            return;
        }
        for (int subArrsNum = arr.length / 2; subArrsNum >= 1; subArrsNum /= 2) {
            //处理每个子数组
            for (int secondElePos = subArrsNum; secondElePos < 2 * subArrsNum; secondElePos++) {
                for (int elePos = secondElePos; elePos < arr.length; elePos += subArrsNum) {
                    int toInsertELePos = elePos;
                    Comparable toInsertEleVal = arr[elePos];
                    for (int orderedElePos = elePos - subArrsNum; orderedElePos >= 0; orderedElePos -= subArrsNum) {
                        if (toInsertEleVal.compareTo(arr[orderedElePos]) < 0) {
                            arr[orderedElePos + subArrsNum] = arr[orderedElePos];
                            toInsertELePos = orderedElePos;
                        } else {
                            toInsertELePos = orderedElePos + subArrsNum;
                            break;
                        }
                    }
                    arr[toInsertELePos] = toInsertEleVal;
                }
            }

        }
    }

时间复杂度

最坏情况下优于O(n^2),详见 希尔排序&选择排序&时间复杂度分析

是原地排序吗

是的,希尔排序不需要使用额外空间

稳定吗

不稳定,插入排序是稳定的,但是希尔排序不是,划分子数组后,是对各个子数组分别进行插入排序,这时可能两个相同的元素在不同的子数组的排序位置是不同的,例如[1,4,3,3,6,5],一次排序后为[1,3,3,4,6,5],"3"的相对位置发生了变化


源码地址github

以上是关于高级排序算法之希尔排序的主要内容,如果未能解决你的问题,请参考以下文章

插入排序变异之希尔排序

(算法三)高级排序(希尔排序和归并排序 )

排序算法之希尔排序

排序算法之希尔排序

图解排序算法之希尔排序

图解排序算法之希尔排序