算法之Shell排序

希尔排序是对插入排序的优化,假如一组数据,最小值在末尾,那么插排的效率较低,需要大量的移动。
希尔排序针对此进行了优化,1959年一个叫shell的哥们,想出了间隙排序法(大牛的脑子就是不一样),啥意思呢?就是把一组数据,通过一定的间隙,看成不同的数组,然后每一组数据在进行插排,间隙为1的的希尔排序就是插排。
来个图:~~
在这里插入图片描述
这个图就是把10个数据分为了5组,然后每2个一小组,每组进行插排,采用的是折半法,间隙为5。10/2
然后把排完序的数组在进行分组,折半思想,间隙为2,每5个一组,进行插排。
5/2
最后在进行分组,间隙为1,最后这次就是普通的插排
2/2

由此可见:
数组长度为10,在折半思想的套路下,三次即可完成排序呢

上代码:

1.希尔排序之交换法

	import java.text.SimpleDateFormat;
import java.util.Arrays;
import java.util.Date;

public class ShellSort {
    public static void main(String[] args) {

        int[] arr = new int[8000000];
        for (int i = 0; i < 8000000; i++) {
            arr[i]=(int)(Math.random()*800000000);
        }
        Date date = new Date();
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH mm ss");
        String format = sdf.format(date);
        System.out.println(format);
        /*System.out.println(Arrays.toString(arr));*/
        int temp = 0;
        boolean flag = false;
        //gap为多少组,/2为每一组的个数
        //最小分组>0,1/2==0.5,将不满足,说明以无法再细分了,循环结束,排序完成
        for (int gap = arr.length / 2; gap > 0; gap /= 2) {
            //gap为多少组,每次循环排序一组
            for (int i = gap; i < arr.length; i++) {
                //遍历每组中的所有元素,步长为gap
                for (int j = i - gap; j >= 0; j -= gap) {
                    if (arr[j] > arr[j + gap]) {
                        flag = true;
                        temp = arr[j];
                        arr[j] = arr[j + gap];
                        arr[j + gap] = temp;
                    }else {
                        break;
                    }
                }
            }

        }
        Date date2 = new Date();
        String format2 = sdf.format(date2);
        System.out.println(format2);

    }

800万数据5S
在这里插入图片描述
2.希尔排序之位移法

import java.text.SimpleDateFormat;
import java.util.Arrays;
import java.util.Date;

public class ShellSort {
    public static void main(String[] args) {

        int[] arr = new int[8000000];
        for (int i = 0; i < 8000000; i++) {
            arr[i] = (int) (Math.random() * 800000000);
        }
        Date date = new Date();
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH mm ss");
        String format = sdf.format(date);
        System.out.println(format);
        /*System.out.println(Arrays.toString(arr));*/




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

            for (int i = gap; i < arr.length; i++) {
                //保存待插入的数
                int j = i;
                //临时变量保存该值
                int temp = arr[j];
                //找位置,当前的数小于前面对应的数,这里j是后面的数
                if (arr[j] < arr[j - gap]) {
                    //只要待插入的数【j】   -  步长>=0,说明还能继续找位置
                    while (j - gap >= 0 && temp < arr[j - gap]) {
                        //移动,当前的数被前面大的数覆盖呢
                        arr[j] = arr[j - gap];
                        //控制下标越界,每发现一个,交换完成往前移动一个步长
                        j -= gap;
                    }
                    //退出循环后即找到位置
                    arr[j] = temp;
                }
            }

          /*  System.out.println(Arrays.toString(arr));*/
        }
        Date date2 = new Date();
        String format2 = sdf.format(date2);
        System.out.println(format2);
    }


}

800万数据4S
在这里插入图片描述

每次折半其实不是最好的间隙方法, 唐纳德·克努特提出了 Kunth序列,即

h=1;
h=3*h+1;

这个序列是根据数组长度动态的划分间隙,提高效率呢

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值