LEIZHANG ' s GitHub

排序算法-希尔排序

排序算法-希尔排序

问题引入

插入排序中存在的问题:

若数据为 2 3 4 5 6 1,则后移的次数明显增多,很影响效率

希尔排序基本介绍

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

基本思想

  • 希尔排序是把记录按下标的一定增量分组
  • 对每组使用直接插入排序算法排序
  • 随着增量逐渐减少,每组包含的关键词越来越多

代码实现(交换式)

package cn.imut.sort;

import java.util.Arrays;

public class ShellSort {
    public static void main(String[] args) {
        int[] arr = {8, 9, 1, 7, 2, 3, 5, 4, 6, 0};
        shellSort(arr);
    }

    public static void shellSort(int[] arr) {
        int temp = 0;
        int count = 0;

        for(int gap = arr.length / 2; gap > 0; gap /= 2) {
            for(int i = gap; i < arr.length; i++) {
                //遍历各组中所有的元素(共gap组,每组有的元素,步长gap)
                for(int j = i - gap; j >= 0; j -= gap) {
                    //如果当前元素大于加上步长后的那个元素,说明交换
                    if(arr[j] > arr[j + gap]) {
                        temp = arr[j];
                        arr[j] = arr[j + gap];
                        arr[j + gap] = temp;
                    }
                }
            }
        }
        System.out.println("希尔排序第" + (++count) + "轮 =" + Arrays.toString(arr));
    }
}

速度测试(80000个数据)

public static void main(String[] args) {
    int[] arr = new int[80000];
    for(int i = 0; i < 80000; i++) {
        arr[i] = (int)(Math.random() * 8000000);        //生成一个[0, 8000000)的数
    }
    Date date1 = new Date();
    SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
    String date1Str = simpleDateFormat.format(date1);
    System.out.println("排序前的时间是 :" + date1Str);

    shellSort(arr);

    Date date2 = new Date();
    String date2Str = simpleDateFormat.format(date2);
    System.out.println("排序后的时间是 :" + date2Str);
}

结论:需要8秒

what???

插入排序只需1秒,希尔排序需要8秒???

因此得出结论,上述代码仅仅为思想上理解的希尔排序!

改进的希尔排序(移位法)

代码如下

public static void shellSort2(int[] arr) {
    for(int gap = arr.length / 2; gap > 0; gap /= 2) {
        //从第gap个元素,逐个插入
        for(int i = gap; i < arr.length; i++) {
            int j = i;
            int temp = arr[j];
            if(arr[j] < arr[j - gap]) {
                while (j - gap >= 0 && temp < arr[j - gap]) {
                    //移动
                    arr[j] = arr[j - gap];
                    j -= gap;
                }
                //退出时,便找到
                arr[j] = temp;
            }
        }
    }
}

结论:这才是希尔排序该有的样子,不到一秒,比冒泡、选择、插入都快

posted @ 2020-04-24 18:58  LEI_Z  阅读(197)  评论(0)    收藏  举报