排序算法学习05_希尔排序(Java)

希尔排序


前言:在博客写这些文章的目的用于记录所学,怕以后忘了,如果哪里写的不对欢迎指正,谢谢!!

学习目标:掌握希尔排序算法的原理和思想

一、前提知识

  排序算法概念、时间复杂度。可前往此网址 排序算法学习01_算法基础介绍阅读

  需要了解直接插入排序

二、希尔排序介绍

    希尔排序(Shellsort),也称递减增量排序算法,是直接插入排序的一种更高效的改进版本。希尔排序是非稳定排序算法

三、希尔排序工作原理

  其实就比直接插入排序多一点,就是分组

  上面讲过,希尔排序也称递减增量排序算法,这个增量,其实就是分组中各个元素的距离递减:每次缩小元素之间的距离
  通过每次缩小分组来执行直接插入排序,经过多次对多个分组排序后,即可得到最终结果。

四、希尔排序算法设计思想

  首先讨论两点:1.如何分组 2.如何缩小分组

  假设选择有这样一条数列{3,2,5,1,7,9,8},要做递增效果:
,这个看作为最原始的分组

  那我们第一次分组时,该分组增量跨度必须够大,这样可保证如果后面存在小的值,可以提前过来。所以,第一次增量值为: Increment = a.length/2,增量为3的构成一组,那么将被分为3组

[3,1,8],[2,7],[5,9],分别对这三个组进行直接插入排序,排序之后元素1就会到前面去了,变成这样

  然后再次缩小增量,除以2,Increment = Increment / 2,现在为增量为1的构成一组,进行直接插入排序

这里就用文字说了:1 和 2 比较,不用换,2和5不用,5和3比较,只移动一次

     1   2   3  5   7   9   8

5和7不用,7和9不用,9和8比较,只移动一次

     1   2   3  5   7   8   9

  当分组到增量为1时,数列只需要简单微调,最后的结果即可出来

  现在我们又回到开头,1.怎么分组,用数组长度除以2    2.怎么缩小分组,再次除以2

  分组和元素变化过程:首次时,组最多,但是此时每个组包含元素最少。慢慢缩小增量,组变少,每个组包含元素变多

  排序时:挑选分组中的值来排序

五、根据以上思路设计希尔排序算法

要求对以下这个数列进行递增排序:{3,2,5,1,7,9,8}

package com.migu.sortingAlgorithm;

import java.util.Arrays;
/**
 * 希尔排序
 */
public class ShellSort {
    public static void main(String[] args) {
        int a[] = {3,2,5,1,7,9,8};
        // 根据前面所讲的增量,来设置循环
        for(int increment = a.length / 2;increment >= 1; increment/=2){
            // 以下结构跟我们上篇所讲的直接插入排序很像
            // 1.从分组后序列的第二位开始走
            for(int i = increment+increment;i < a.length;i++){
                int insertVal = a[i]; // 保存待插入元素
                int insertIndex= i-increment;  // 插入所在索引,从待插入元素的前一位开始判断,也是从后往前走
                while (insertIndex >= 0 && a[insertIndex] > insertVal){
                    a[insertIndex+increment] = a[insertIndex];
                    insertIndex-=increment;
                }
                a[insertIndex+increment] = insertVal; // 执行插入,while循环结束后,还会减掉增量,所以要加上去
            }
        }

        System.out.println(Arrays.toString(a)); // 调用工具类输出
    }
}

  还有一种方法:是跟冒泡排序结合使用,我称他为希尔式冒泡排序,在for循环里放置如下代码

// 根据前面所讲的增量,来设置循环
for(int increment = a.length / 2;increment >= 1; increment/=2){
    // 对全部分组执行冒泡,当增量为1时,就相当于普通冒泡排序,但这个冒泡排序此时已经不怎么需要冒了
    for(int i = increment;i < a.length;i++){
        int j = i; 
        // 从后往前开始冒泡
        while (j-increment >=0 && a[j] < a[j - increment]) {
            int temp = a[j];
            a[j] = a[j - increment];
            a[j - increment] = temp;
            j-=increment;
        }
    }
}

  我在我笔记本用Date类测了一下,在100万条随机数(0~100万)的数据下,两者运算都在一秒内,差不了多少

六、时间复杂度

  网上所说该算法最坏情况为O(n),但是我就觉得该玩意很快,前面说过了,分别对希尔排序两种方式的算法使用100万条数据进行排序,时间都在1秒之内,可能因为硬件的问题,但我这台电脑配置真的很低

七、总结

  希尔排序算法通过把原本大的数列划分成一个个组来进行排序,最后再进行总体排序时,经过简单微调即可排序完毕,只能说太牛了

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值