希尔排序是如何对插入排序进行优化的?

简单插入排序存在的问题

数组 arr =[2,3,4,5,6,1] 这个时候我们要插入的数1,过程是这样的;
[2,3,4,5,6,6]
[2,3,4,5,5,6]
[2,3,4,4,5,6]
[2,3,3,4,5,6]
[2,2,3,4,5,6]
[1,2,3,4,5,6]

当要插入的数是较小的数时,后移的次数明显增对,对效率有一定的影响。希尔排序就对简单插入排序进行了一定的优化;

希尔排序法介绍

希尔排序是希尔于1959年提出的一种排序算法。希尔排序也是一种插入排序,它是简单插入排序经过改进之后的一个更高效的版本,也称之为缩小增量排序

希尔排序的基本思想

希尔排序是记录按下标的一定增量分组,对分组使用直接插入排序算法排序;随着增量分组逐渐减少,每组包含的关键词越来越多。当增量分组减至1时,整个文件恰被分为一组,算法便终止。

方法的实质其实时分组插入排序算法,就是对每个每组进行插入排序。

图解举例说明:

请添加图片描述

第一次分组进行排序:

将数组分为step(步长)=length/2个组 。每个组有两个元素。每个元素之间的间隔为step,即每间隔step个数的数为一组;请添加图片描述
分为5组;相邻间隔为step的元素为同一组,索引分别为【0,5】,【1,6】,【2,7】,【3,8】,【4,9】,同一组之间的间隔为步长。 然后对同组的值进行插入排序;
排完之后的顺序为:[3 ,5 ,1 ,6 ,0 ,8 ,9 ,4 ,7 ,2]

第二次分组进行排序

请添加图片描述
第二次在第一次步长的基础上在进行分组,即step=length/2/2.
由图:10/2/2=2,分为了两组,然后对两组中的元素分别进行插入排序。
同一组的元素之间间隔step=2;索引为【0,2,4,6,8】【1,3,5,7,9】。
排完之后【0 ,2 ,1 ,4 ,3 ,5 ,7 ,6 ,9 ,8】

第三次分组进行排序

请添加图片描述
step = length/2/2/2 = 1;当增量为一1,就是最后一次排序。
直接对分组中的元素排序即可。

Java代码实现:

交换插入排序

 public static void shellSort(int[] arr) {
        if (arr.length!=0) {

            //用来存储临时变量
            int temp;
            //首先分为n/2组,即每2个为一组。则每组元素之间的间隔为n/2。用step来表示步长,即同组之间的间隔。
            for (int step = arr.length / 2; step > 0; step /= 2) {
                //分为了n/2组,则前n/2个元素都是不同组的元素,默认第一个元素都是有序的,从每组的第二个数进行插入排序。跟同组前面有序的进行比较
                //直到遍历到最后一个数
                for (int i = step; i < arr.length; i++) {
                    //每次跟前面同组的元素进行比较
                    for (int j = i - step; j >= 0; j -= step) {
                        if (arr[j] > arr[j + step]) {
                            temp = arr[j];
                            arr[j] = arr[j + step];
                            arr[j + step] = temp;
                        }
                    }
                }

            }
        }
    }

后移插入排序

public static void shellSort(int[] arr) {
        if (arr.length != 0) {

            for (int step = arr.length / 2; step > 0; step /= 2) {

                for (int i = step; i < arr.length; i++) {
                    int j = i;
                    int value = arr[j];

                    while (j - step >= 0 && value < arr[j - step]) {
                        arr[j] = arr[j - step];
                        j -= step;
                    }

                    arr[j] = value;
                }
            }

        }
    }    

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Vivien_o.O

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值