挑战七大排序算法-02希尔排序

23 篇文章 0 订阅
15 篇文章 0 订阅

算法如其名,肯定是某个优秀的学者Shell提出了这种排序算法;

1.定义

是简单插入排序的改进版,它与插入排序不同之处在于:希尔排序会优先比较距离较远的元素。
希尔排序又称缩小增量排序,是对直接插入排序的优化;

2.基本思想

该方法实质上是一种分组插入方法

比较相隔较远距离(称为增量)的数,使得数移动时能跨过多个元素,则进行一次比较就可能消除多个元素交换;

(1)算法先将要排序的一组数按某个增量d分成若干组;

(2)每组中记录的下标相差d.对每组中全部元素进行排序

(3)然后再用一个较小的增量对它进行,在每组中再进行排序

(4)当增量减到1时,整个要排序的数被分成一组,排序完成。

3.下面的栗子看过来

3.1确定增量step

有以下两种方法,任选一种即可

(1)step = array.length/3+1

(2)step = array.length/2

3.2step = 6/2 = 3时,如下图所示,将数据元素分成了三组

对第一组元素进行排序,5>3,即array[0]>array[0+step];将元素5放到array[3],元素1放到array[0]的位置;
对第二组元素进行排序,4>3,即array[1]>array[1+step];将元素4放到array[4],元素3放到array[1]的位置;
对第三组元素进行排序,6>2,即array[2]>array[2+step];将元素4放到array[5],元素2放到array[2]的位置;

3.3step = 3/2 = 1时,如下图所示,将数据元素分成了一组

当step = 1,即就是直接插入排序(在上一篇博客哦);

插入排序后的结果是:

4.算法代码实现

4.1希尔排序代码实现

    public static void shellSort(int[] array){
        if(array.length <= 1){
            return;
        }else{
            int step = array.length;
            while (true){
                //step的两种规定
                step = step/2;
                //step = step/3+1
                insertSortWithStep(array,step);
                //step=1就是直接插入排序
                if (step == 1){
                    break;
                }
            }
        }
    }

    private static void insertSortWithStep(int[] array, int step) {
        for(int i = step;i < array.length;i++){
            int value = array[i];
            int j = i-step;
            for(;j >= 0 && array[j] > value;j-=step){
                array[j+step] = array[j];
            }
            array[j+step] = value;
        }
    }

4.2测试一下

public static void main(String[] args) {

        int[] a = {2,5,1,7,3,6,9};

        int[] b = a.clone();
        shellSort(b);
        System.out.println(Arrays.toString(b));

        //通过Arrays.sort进行验证排序结果
        int[] c = a.clone();
        Arrays.sort(c);
        System.out.println(Arrays.toString(c));

        System.out.println(Arrays.equals(b,c));
        //testSpeed();
}

看看结果吧:

bingo,正确哦

4.3接下来我们测一下速度

还是100000个数据

public static void testSpeed(){
        Random random = new Random(20191019);
        int[] a = new int[100000];
        for (int i = 0;i < 100000;i++){
            a[i] = random.nextInt(200000);
        }
        long begin = System.nanoTime();
        shellSort(a);
        long end = System.nanoTime();
        double ms = (end-begin)/1000/1000;
        System.out.printf("一共耗时:%.5f 毫秒%n",ms);
}

这次只用了49毫秒诶,比直接插入排序还厉害;

5.源代码

package sort.insertSort;

import java.util.Arrays;
import java.util.Random;


/**
 * @Author:Star
 * @Date:Created in 9:30 2019/10/19
 * @Description:希尔排序算法
 * 时间复杂度:最好:O(n)平均:O(n^1.3)最坏:O(n^2)
 * 空间复杂度:O(1)(原地排序)
 * 稳定性:不稳定(因为两个相同的数难以保证分到一个组里面去比较)
 */
public class ShellSort {

    public static void shellSort(int[] array){
        if(array.length <= 1){
            return;
        }else{
            int step = array.length;
            while (true){
                //step的两种规定
                step = step/2;
                //step = step/3+1
                insertSortWithStep(array,step);
                //step=1就是直接插入排序
                if (step == 1){
                    break;
                }
            }
        }
    }

    private static void insertSortWithStep(int[] array, int step) {
        for(int i = step;i < array.length;i++){
            int value = array[i];
            int j = i-step;
            for(;j >= 0 && array[j] > value;j-=step){
                array[j+step] = array[j];
            }
            array[j+step] = value;
        }
    }

    public static void testSpeed(){
        Random random = new Random(20191019);
        int[] a = new int[100000];
        for (int i = 0;i < 100000;i++){
            a[i] = random.nextInt(200000);
        }
        long begin = System.nanoTime();
        shellSort(a);
        long end = System.nanoTime();
        double ms = (end-begin)/1000/1000;
        System.out.printf("一共耗时:%.5f 毫秒%n",ms);
    }

    public static void main(String[] args) {

//        int[] a = {2,5,1,7,3,6,9};
//
//        int[] b = a.clone();
//        shellSort(b);
//        System.out.println(Arrays.toString(b));
//
//        //通过Arrays.sort进行验证排序结果
//        int[] c = a.clone();
//        Arrays.sort(c);
//        System.out.println(Arrays.toString(c));
//
//        System.out.println(Arrays.equals(b,c));
        testSpeed();
    }
}

期待留言和分享哦,哈哈哈

一起学习,一起进步哦

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值