图解排序算法(二)之希尔排序

  希尔排序是希尔(Donald Shell)于1959年提出的一种排序算法。希尔排序也是一种插入排序,它是简单插入排序经过改进之后的一个更高效的版本,也称为缩小增量排序,同时该算法是冲破O(n2)的第一批算法之一。本文会以图解的方式详细介绍希尔排序的基本思想及其代码实现。

基本思想

  希尔排序是把记录按下标的一定增量分组,对每组使用直接插入排序算法排序;随着增量逐渐减少,每组包含的关键词越来越多,当增量减至1时,整个文件恰被分成一组,算法便终止。

  简单插入排序很循规蹈矩,不管数组分布是怎么样的,依然一步一步的对元素进行比较,移动,插入,比如[5,4,3,2,1,0]这种倒序序列,数组末端的0要回到首位置很是费劲,比较和移动元素均需n-1次。而希尔排序在数组中采用跳跃式分组的策略,通过某个增量将数组元素划分为若干组,然后分组进行插入排序,随后逐步缩小增量,继续按组进行插入排序操作,直至增量为1。希尔排序通过这种策略使得整个数组在初始阶段达到从宏观上看基本有序,小的基本在前,大的基本在后。然后缩小增量,到增量为1时,其实多数情况下只需微调即可,不会涉及过多的数据移动。

  我们来看下希尔排序的基本步骤,在此我们选择增量gap=length/2,缩小增量继续以gap = gap/2的方式,这种增量选择我们可以用一个序列来表示,{n/2,(n/2)/2...1},称为增量序列。希尔排序的增量序列的选择与证明是个数学难题,我们选择的这个增量序列是比较常用的,也是希尔建议的增量,称为希尔增量,但其实这个增量序列不是最优的。此处我们做示例使用希尔增量。

代码实现

  在希尔排序的理解时,我们倾向于对于每一个分组,逐组进行处理,但在代码实现中,我们可以不用这么按部就班地处理完一组再调转回来处理下一组(这样还得加个for循环去处理分组)比如[5,4,3,2,1,0] ,首次增量设gap=length/2=3,则为3组[5,2] [4,1] [3,0],实现时不用循环按组处理,我们可以从第gap个元素开始,逐个跨组处理。同时,在插入数据时,可以采用元素交换法寻找最终位置,也可以采用数组元素移动法寻觅。希尔排序的代码比较简单,如下:

1 package sortdemo; 2  3 import java.util.Arrays; 4  5 /** 6  * Created by chengxiao on 2016/11/24. 7  */ 8 public class ShellSort { 9     public static void main(String []args){10         int []arr ={1,4,2,7,9,8,3,6};11         sort(arr);12         System.out.println(Arrays.toString(arr));13         int []arr1 ={1,4,2,7,9,8,3,6};14         sort1(arr1);15         System.out.println(Arrays.toString(arr1));16     }17 18     /**19      * 希尔排序 针对有序序列在插入时采用交换法20      * @param arr21      */22     public static void sort(int []arr){23         //增量gap,并逐步缩小增量24        for(int gap=arr.length/2;gap>0;gap/=2){25            //从第gap个元素,逐个对其所在组进行直接插入排序操作26            for(int i=gap;i<arr.length;i++){27                int j = i;28                while(j-gap>=0 && arr[j]<arr[j-gap]){29                    //插入排序采用交换法30                    swap(arr,j,j-gap);31                    j-=gap;32                }33            }34        }35     }36 37     /**38      * 希尔排序 针对有序序列在插入时采用移动法。39      * @param arr40      */41     public static void sort1(int []arr){42         //增量gap,并逐步缩小增量43         for(int gap=arr.length/2;gap>0;gap/=2){44             //从第gap个元素,逐个对其所在组进行直接插入排序操作45             for(int i=gap;i<arr.length;i++){46                 int j = i;47                 int temp = arr[j];48                 if(arr[j]<arr[j-gap]){49                     while(j-gap>=0 && temp<arr[j-gap]){50                         //移动法51                         arr[j] = arr[j-gap];52                         j-=gap;53                     }54                     arr[j] = temp;55                 }56             }57         }58     }59     /**60      * 交换数组元素61      * @param arr62      * @param a63      * @param b64      */65     public static void swap(int []arr,int a,int b){66         arr[a] = arr[a]+arr[b];67         arr[b] = arr[a]-arr[b];68         arr[a] = arr[a]-arr[b];69     }70 }

总结

  本文介绍了希尔排序的基本思想及其代码实现,希尔排序中对于增量序列的选择十分重要,直接影响到希尔排序的性能。我们上面选择的增量序列{n/2,(n/2)/2...1}(希尔增量),其最坏时间复杂度依然为O(n2),一些经过优化的增量序列如Hibbard经过复杂证明可使得最坏时间复杂度为O(n3/2)。希尔排序的介绍到此为止,关于其他排序算法的介绍也会陆续更新,谢谢支持。

(0)

相关推荐

  • 冒泡排序、插入排序、选择排序、希尔排序

    排序是一个非常经典的问题,它以一定的顺序对一个数组(或一个列表)中的项进行重新排序(可以进行比较,例如整数,浮点数,字符串等)(增加,非递减,递减, 增加,词典等). 有许多不同的排序算法,每个都有其 ...

  • Python|插入排序之希尔排序

    引言 希尔排序(Shell's Sort)是插入排序的一种又称"缩小增量排序",是直接插入排序算法的一种更高效的改进版本.希尔排序是非稳定排序算法. 问题描述 希尔排序是把记录按下 ...

  • 希尔排序

    希尔排序(Shell Sort)是插入排序的一种.也称缩小增量排序,是直接插入排序算法的一种更高效的改进版本.希尔排序是非稳定排序算法.该方法因DL.Shell于1959年提出而得名. 希尔排序是把记 ...

  • PHP数据结构-插入类排序:简单插入、希尔排序

    插入类排序:简单插入.希尔排序 总算进入我们的排序相关算法的学习了.相信不管是系统学习过的还是没有系统学习过算法的朋友都会听说过许多非常出名的排序算法,当然,我们今天入门的内容并不是直接先从最常见的那 ...

  • Python | 深入希尔排序世界

    引言 希尔排序(Shell Sort),是插入排序的一种又称"缩小增量排序",同时它是非稳定排序算法.该方法因 D.L.Shell 于 1959 年提出而得名. 问题描述 希尔排序 ...

  • 十种排序算法总结(冒泡、插入、选择、希尔、归并、堆、快速,计数,桶,基数)

    #include<iostream> using  namespace std; void swap1( int *left,  int *right) {      int temp = ...

  • 图解七大排序算法

    "排序是计算机的核心内容.事实上,从很多方面看,如果没有排序,计算机就不会变成现实." <算法之美:指导工作与生活的算法> 排序算法,或许是我们日常最常见也是使用频率最 ...

  • Java排序算法(四)希尔排序2

    希尔排序移步法:分组+直接插入排序组合 一.测试类SortTest import java.util.Arrays; public class SortTest { private static fi ...

  • C 基础语法梳理:算法丨十大排序算法(二)

    归并排序 归并排序:把数据分为两段,从两段中逐个选最小的元素移入新数据段的末尾.可从上到下或从下到上进行. /***************** 迭代版*****************///整數或浮 ...

  • 「排序算法」—图解双轴快排

    首发公众号:bigsai 前言 在排序算法中,快排是占比非常多的一环,但是快排其思想一直被考察研究,也有很多的优化方案.这里主要讲解双轴快排的思想和实现. 首先,双轴快排也是一种快排的优化方案,在JD ...

  • 排序算法之希尔排序及其增量序列

    希尔排序 其他排序方法:选择排序.冒泡排序.归并排序.快速排序.插入排序.希尔排序.堆排序 思想 希尔排序大概就是,选一组递减的整数作为增量序列.最小的增量必须为1:DM>DM−1>... ...

  • [数据结构] 动图演示 代码实现八大排序(插入、希尔、选择、堆、冒泡、快速、归并、基数/桶)

    2019-04-18 18:22:04 giturtle 码龄3年 关注 排序 1. 插入排序 2. 希尔排序 3. 选择排序 4. 堆排序 5. 冒泡排序 6. 快速排序 1)Hover法 2)挖坑 ...

  • 七大排序算法总结

    以下所有动图均来源于一像素博客园 以下代码均使用C 编写 完整代码请到这里下载 稳定排序算法:冒泡排序.插入排序.归并排序 时间复杂度不受数据影响:选择排序.归并排序.堆排序 时间复杂度基本小于n2: ...