zoukankan      html  css  js  c++  java
  • 希尔排序

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

    概述

      希尔排序,听名字很奇怪,就是以这个算法的发明人的名字命名的,这个排序算法是对插入排序的一个优化版本,本来以为优化的很好,仔细研究了一下,很失望,优化的并不怎么样,最差的情况时间复杂度依然是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]);
            }
        }
    
    }
  • 相关阅读:
    isObject:判断数据是不是引用类型的数据 (例如: arrays, functions, objects, regexes, new Number(0),以及 new String(''))
    isPrimitive:检测数据是不是原始数据
    FastDFS集群部署
    大数据系列之分布式大数据查询引擎Presto
    大数据系列之数据仓库Hive原理
    大数据系列之数据仓库Hive中分区Partition如何使用
    关于Java中final关键字的详细介绍
    关于分布式存储系统中-CAP原则(CAP定理)与BASE理论比较
    过拟合及其对策
    深入理解L1、L2正则化
  • 原文地址:https://www.cnblogs.com/gunduzi/p/13259796.html
Copyright © 2011-2022 走看看