Fork me on GitHub

希尔排序

本文参考:图解排序算法(二)之希尔排序,大家看这篇文章就够了,不用看我的,我的文章为了给自己做个笔记,方便自己以后看

概述

  希尔排序,听名字很奇怪,就是以这个算法的发明人的名字命名的,这个排序算法是对插入排序的一个优化版本,本来以为优化的很好,仔细研究了一下,很失望,优化的并不怎么样,最差的情况时间复杂度依然是O(n2),通过优化增量序列可以使时间复杂度减小,什么是增量序列呢?下面会介绍。

 

核心思想

  由于插入排序在小数据集并且基本有序的数据集上表现较好,如果一个数据集很大并且排序很乱,那插入排序效果很一般,基于以上的原因,希尔排序其实就是针对这两点做的优化。

  针对第一点,数据集大时,表现差:希尔排序把大数据集分成一个一个的小段(注意:并不是把一个数组分成多个小数组,逻辑上分的)

  针对第二点,数据排序比较乱:希尔排序是先在每一小段上排序,但是整体并不是有序的,然后这样就可以使整个数据集没有那么乱了,再采用插入排序

下面会通过举例的方式介绍希尔排序处理过程:

举例:2,4,3,1,5,7,6,9,8,0

要求:采用希尔排序算法进行排序

实现过程如下:

  • 第一步:数据集数据个数为10,第一次把数组分成5组,也就是10/2,结果为:[2,7], [4,6], [3,9], [1,8], [5,0],分成这5组,注意是逻辑分组,不是物理分组
  • 第二步:对第一步的分组结果进行排序,结果为2,4,3,1,0,7,6,9,8,5,进过第一轮,5和0发生了交换
  • 第三步:将数据集分成2组,也就是5/2(向下取整),分组结果为:[2,3,5,6,8],  [4,1,7,9,0]
  • 第四步:对第三步的结果排序,结果为:2,0,3,1,5,4,6,7,8,9,红色为第一组的,黑色为第二组的
  • 第五步:对整个数据集排序,就是2/2,结果为:[0,1,2,3,4,5,6,7,8,9]

上面的过程中,是先把数组分成5份,之后是2份,之后是1份,大家可能困惑为什么这样分,其实这个分法就是希尔推荐的分法,但是这种并不是最好的分法,后来又有其他人提出了别的方法。其实本文的增量序列为{1,2,4,8,...}这种,但是由于数组长度是10,导致变成了1,2,5,^_^,如果数组长度为16,那就可以变成1,2,4,8这种。

 

另外两种分法:(参考:希尔排序--简单易懂图解

Hibbard提出了另一个增量序列{1,3,7,...,2^k-1},这种序列的时间复杂度(最坏情形)为O(n^1.5)

Sedgewick提出了几种增量序列,其最坏情形运行时间为O(n^1.3),其中最好的一个序列是{1,5,19,41,109,...}

 

上面哔哔叭叭那么多,看的dan疼,看代码吧

 

代码实现

/**
 * @author: steve
 * @date: 2020/7/7 10:13
 * @description: 希尔排序
 */
public class ShellSort {

    public static int array[] = {72, 6, 57, 88, 60, 42, 83, 73, 48, 8, 1};

    //gap 间隔

    public static void shellSort(){
        //这里的增量采用希尔增量,所谓增量其实就是你要把数组分成一个部分,这里是一直除于二
        //相当于第一次分成5份,第二次分成2份,第三次分成1份,结束
        int gap = array.length/2;
        int j;
        while(gap > 0){

            for (int i = gap; i < array.length; i++) {
                j = i;

                //这里的while循环使用的很巧妙吧,相当于是从后往前一个一个交换,最终找到目标要插入的位置
                while( j >= gap && array[j-gap] > array[j]){
                    swap(j-gap,j);
                    j = j-gap;
                }
            }

            gap = gap/2;
        }
    }

    public static void swap(int i, int j){
        int temp = 0;
        temp = array[i];
        array[i] = array[j];
        array[j] = temp;
    }

    public static void main(String[] args) {
        shellSort();

        for (int i = 0; i < array.length; i++) {
            System.out.println(array[i]);
        }
    }

}

 

posted @ 2020-07-07 11:30  猿起缘灭  阅读(189)  评论(0编辑  收藏  举报