希尔排序详解(Shell Sort)

简介: 希尔排序详解

一、简单释义

1、算法概念

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

2、算法目的

 把无序数组通过分组,分组之间比较进行移动,最后形成一个有序数组  (文中以升序为例)

3、算法思想

 先取一个小于n的整数d1作为第一个增量,把文件的全部记录分组。所有距离为d1的倍数的记录放在同一个组中。先在各组内进行直接插入排序;然后,取第二个增量d2,以此类推。

二、核心思想

先–对已有的数列进行分组,明确增量;

中–每个分组使用直接插入排序进行位置交换;

后–将每个分组执行直接插入排序后的结果在进行直接插入排序;

三、图形展示

宏观展示

2d68cf5696ea4d3c84e1650634acce83.png

微观展示

 以3、5、9、2、4、7这个数组为例,进行每一步排序的拆分。

01df4715d6034e1586241b5249923262.png

 1、第一次排序:首先明确第一次分组的增量值,用数组的的长度/2。6/2=3,将数组分为增量为3的三个分组,三个分组使用直接插入排序进行位置交换

aca7fd8f55ea44608a82f0adf51816ee.png

 2、第二次排序:首先根据第一次的增量来计算第二次分组的增量,用第一次的增量/2得到第二次的增量,然后进行分组,分组完毕之后使用直接插入排序交换位置。

ee7bef2fe2174ce3b504e07a315bc355.png

 3、第三次排序:首先根据第二次的增量来计算第三次分组的增量,直到增量为1进行最后一次的排序。

四、算法实现

实现思路

 将图形化展示的过程转换成对应的开发语言,本文中主要以Java语言为例来进行算法的实现。

 1、定义一个list集合用来存储待排序的数

 2、获取待排序中的中间值作为分组的增量值

 3、分组完成之后进行第二次获取增量分组

 4、以此类推,直到增量值为1得到最终的排序结果

 没把整个过程描述清楚实现起来才会更加容易!!!

代码实现

/**
 * @BelongsProject: demo
 * @BelongsPackage: com.wzl.Algorithm.InsertionSort
 * @Author: Wuzilong
 * @Description: 希尔排序
 * @CreateTime: 2023年5月1日
 * @Version: 1.0
 */
public class ShellSort {
    public static void main(String[] args) {
        int[] arr = {3, 5, 9, 2, 4, 7};
        System.out.println("排序之前数组:");
        System.out.println(Arrays.toString(arr));
        //希尔排序
        insertionSort(arr);
        System.out.println("希尔排序后数组:");
        System.out.println(Arrays.toString(arr));
    }
    private static int[]  insertionSort(int[] arr){
        if(arr == null || arr.length <= 1){
            return arr;
        }
        //希尔排序  升序
        for (int d = arr.length / 2;d>0;d /= 2){ //d:增量  7   3   1
            System.out.println("增量取值:" + d);
            for (int i = d; i < arr.length; i++){
                //i:代表即将插入的元素角标,作为每一组比较数据的最后一个元素角标
                //j:代表与i同一组的数组元素角标
                for (int j = i-d; j>=0; j-=d){ //在此处-d 为了避免下面数组角标越界
                    if (arr[j] > arr[j + d]) {// j+d 代表即将插入的元素所在的角标
                        //符合条件,插入元素(交换位置)
                        swap(arr,j,j+d);
                    }
                }
            }
        }
        return arr;
    }
    public static void swap(int[] arr,int a,int b)
    {
        int temp = arr[a];
        arr[a] = arr[b];
        arr[b] = temp;
    }
}

运行结果

b3dae65126a94eb5a65d05f454d7862c.png

五、算法描述

1、问题描述

 每一步将一个待排序的元素,按其排序码的大小,插入到前面已经排好序的一组元素的适当位置上去,直到元素全部插入为止

2、算法过程

整个算法过程分为以下几步:

 1)通过数组的长度/2得到第一趟排序的增量,按照增量进行分组。

 2)每个分组使用直接插入排序进行位置的交换

 3)通过第一趟排序的增量/2得到第二次排序的增量,向上取整,在按照增量进行分组。

 4)每个分组使用直接插入排序进行位置的交换

 5)直到得到的增量为1时,进行的直接插入排序的结果为希尔排序的结果。

3、算法总结

 直接插入排序是由两层嵌套循环组成的。外层循环标识并决定待比较的数值。内层循环为待比较数值确定其最终位置。直接插入排序将待比较的数值与它的前一个数值进行比较,所以外层循环是从第二个数值开始的。当前一数值比待比较数值大的情况下继续循环比较,直到找到比待比较数值小的并将待比较数值置入其后一位置,结束该次循环。

六、算法分析

1、时间复杂度

 首先直接插入排序是一个稳定的排序算法;最好的情况下,也就是排序本身是有序的,共需比较n-1次,因为没有移动的记录,时间复杂度为O(n)。最坏的情况下,即排序表是逆序的情况,时间复杂为O(n²)。

2、空间复杂度

 算法的空间复杂度并不是计算实际占用的空间,而是计算整个算法的辅助空间单元的个数。在直接插入排序中只使用了i,j,temp这三个辅助空间单元,所以空间复杂度是O(1)。

3、算法稳定性

 由于多次插入排序,我们知道一次插入排序是稳定的,不会改变相同元素的相对顺序,但在不同的插入排序过程中,相同的元素可能在各自的插入排序中移动,最后其稳定性就会被打乱,所以shell排序是不稳定的。


相关文章
|
6月前
|
Shell 数据安全/隐私保护
shell中的通配符 熟悉grep、cut、sort等小工具和shell中的通配符的使用
shell中的通配符 熟悉grep、cut、sort等小工具和shell中的通配符的使用
69 0
|
6月前
|
搜索推荐 算法 Java
sort-06-shell sort 希尔排序算法详解
这是一个关于排序算法的系列文章摘要。文章汇总了各种排序算法,包括冒泡排序、快速排序、选择排序、堆排序、插入排序、希尔排序、归并排序、计数排序、桶排序以及大文件外部排序。特别地,希尔排序是一种改进的插入排序,通过使用不同的步长对元素进行分组排序,以提高效率。算法最终以较小的步长进行排序,接近线性时间复杂度。文章还提供了Java代码实现,并举例说明了希尔排序的过程。所有内容可在开源项目[https://github.com/houbb/sort](https://github.com/houbb/sort)中找到。
|
6月前
|
搜索推荐 算法 Shell
【Shell 命令集合 文档编辑 】Linux 排序命令 sort命令使用指南
【Shell 命令集合 文档编辑 】Linux 排序命令 sort命令使用指南
70 0
|
6月前
|
算法 搜索推荐 Shell
【408数据结构与算法】—希尔排序 Donald Shell(十七)
【408数据结构与算法】—希尔排序 Donald Shell(十七)
|
算法 搜索推荐 Shell
|
存储 搜索推荐 算法
十大排序之Shell Sort 希尔排序
十大排序之Shell Sort 希尔排序
|
Shell Windows
【Shell编程】字符处理命令sort和wc
【Shell编程】字符处理命令sort和wc
104 0
|
Shell 数据安全/隐私保护
shell中的通配符 熟悉grep、cut、sort等小工具和shell中的通配符的使用(下)
shell中的通配符 熟悉grep、cut、sort等小工具和shell中的通配符的使用
shell中的通配符 熟悉grep、cut、sort等小工具和shell中的通配符的使用(中)
shell中的通配符 熟悉grep、cut、sort等小工具和shell中的通配符的使用
|
搜索推荐 算法 Shell
【408数据结构与算法】—希尔排序 Donald Shell(十七)
先将整个待排记录序列分割成若干子序列,分别进行直接插入排序,待整个序列中的记录基本有序时,再对全体记录进行一次直接插入排序
【408数据结构与算法】—希尔排序 Donald Shell(十七)