Java 希尔排序

52 阅读4分钟

image.png 开启掘金成长之旅!这是我参与「掘金日新计划 · 12 月更文挑战」的第4天,点击查看活动详情

前序

上一篇: 插入排序

希尔排序

理论

关于希尔排序的话,其实就是对于前面上一篇的插入排序的升级版,我们可以简单回顾一下插入排序哈:

限定最左边是有序的数据从第一个开始 fori 往后一个个 的插入排序 进行排序处理;而希尔排序是给予插入排序的改良版本 : 原则都是右边是最小的 ,但是呢插入算法 不再限定于从左边第一个开始 而是根据一定的 gap 间隙量 将原本的数据排序进行 分段化处理 ,换言之:

  • 原本的插入排序 对于从头到尾就一个 排序比较

  • 改良之后,他进行根据一定间隙量将一组数据分成多组 然后呢 在多组之间进行重排序 ,当之后的间隙量==1 时 再将数据进行最后一遍处理将数据位置不对的再次进行一次排序处理 ,相对而言 对于原本的数据在 gap 不等于1时已经存在部分数据是排序成功的 就不需要 交换处理了。

  • 其实对于改良来说哈我觉得是这样的:

    • 具体的交换分组提前进行了 就是我使用 gap 将数据提前分组 然后将分好的组 内的数据进行排序 ,然后呢 ,当gap =1 的时候就分成了 原本的for i 数据 这个时候由于原本的一些数据的顺序已经被提前排序了 所以 会导致后面的交换数据的次数少了
    • 然后后面就不会进行数据交换了 减少了交换的内容
    • 有点类似于分组插入处理了 分治 发的雏形

实践

coding


/***
 * shellSort 测试
 */
@Test
public void shellSortTest() {

    int[] ints = {1, 3, 5, 8, 2, 2, 7, 7, 6, 88, 23, 56, 21, 15};

    System.out.println("原始数组数据");
    for (int i = 0; i < ints.length; i++) {
        System.out.print(ints[i] + ",");
    }
    long l = System.nanoTime();
    int length = ints.length;
    int temp;
    int gap = 2;
    // 这个地方用于限定分组情况  常用的 gap  一般  选择 2  或者 length/3+1
    // initIndex 表示初始化开始比较的插入判断数据    initIndex /= gap 再次gap 可以将 原本的 间隙量 由大的转换到 1 
    for (int initIndex = length / gap; initIndex >= 1;  initIndex /= gap) {
        System.out.println("当前组数以及gap数" + initIndex);
        //step/2 之后呢进行更小力度的其他分组统计
        for (int i = initIndex; i < length; i++) {
            // 数据处理范围
            System.out.println("数据处理范围" + i + "~" + length);
            temp = ints[i];
            int j = i - initIndex;
            while (j >= 0 && ints[j] > temp) {
                System.out.println("交换的数据索引:" + j + "to" + (j + initIndex));
                ints[j + initIndex] = ints[j];
                j -= initIndex;
            }
            ints[j + initIndex] = temp;
        }
    }

    // 使用纳秒计算时间信息
    System.out.println("耗时" + (System.nanoTime() - l));
    System.out.println("排序之后的数据");
    for (int i = 0; i < ints.length; i++) {
        System.out.print(ints[i] + ",");
    }
}

测试结果

为了便于理解我将打印的内容复制出来

原始数组数据
1,3,5,8,2,2,7,7,6,88,23,56,21,15,
当前组数以及gap7
数据处理范围7~14
数据处理范围8~14
数据处理范围9~14
数据处理范围10~14
数据处理范围11~14
数据处理范围12~14
数据处理范围13~14

当前组数以及gap3
数据处理范围3~14
数据处理范围4~14
交换的数据索引:1to4
数据处理范围5~14
交换的数据索引:2to5
数据处理范围6~14
交换的数据索引:3to6
数据处理范围7~14
数据处理范围8~14
数据处理范围9~14
数据处理范围10~14
数据处理范围11~14
数据处理范围12~14
交换的数据索引:9to12
数据处理范围13~14
交换的数据索引:10to13


当前组数以及gap1
数据处理范围1~14
数据处理范围2~14
数据处理范围3~14
数据处理范围4~14
交换的数据索引:3to4
数据处理范围5~14
交换的数据索引:4to5
数据处理范围6~14
数据处理范围7~14
交换的数据索引:6to7
数据处理范围8~14
交换的数据索引:7to8
交换的数据索引:6to7
交换的数据索引:5to6
数据处理范围9~14
数据处理范围10~14
交换的数据索引:9to10
数据处理范围11~14
数据处理范围12~14
数据处理范围13~14
交换的数据索引:12to13
交换的数据索引:11to12


耗时1236100
排序之后的数据
1,2,2,3,5,6,7,7,8,15,21,23,56,88,

总结

这里做一次总结了: 首先希尔排序是使用 插入排序的 基本上进行修改的 将原本属于进行数据的提起插入处理 ,量化数据全部的插入 交换时间 但是这个交换的话由于不是从最左端开始的所以是不稳定的,可能会导致 复合 一定顺序的数据位置进行交换了。

image.png

Ending

下一篇: 归并排序