码迷,mamicode.com
首页 > 编程语言 > 详细

高级排序算法之希尔排序

时间:2020-04-10 00:37:31      阅读:77      评论:0      收藏:0      [点我收藏+]

标签:希尔   举例   数据   algo   稳定性   额外   介绍   并且   github   

前言

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

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

  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

高级排序算法之希尔排序

标签:希尔   举例   数据   algo   稳定性   额外   介绍   并且   github   

原文地址:https://www.cnblogs.com/alonwang/p/12670447.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!