其他分享
首页 > 其他分享> > 希尔排序

希尔排序

作者:互联网

一 算法

一个由h个有序子数组组成的数组。

希尔排序的详细轨迹(各种插入)

希尔排序可视化轨迹

二 代码

package sort;

import common.StdIn;
import common.StdOut;

/**
* @className: Shell
* @description: 希尔排序
* @date: 2021/2/26
* @author: cakin
*/
public class Shell {

    private Shell() {
    }

    /**
     * 功能描述:希尔排序算法
     *
     * @param a 数组
     * @author cakin
     * @date 2021/2/27
     */
    public static void sort(Comparable[] a) {
        int n = a.length;

        // 1, 4, 13, 40, 121, 364, 1093, ...
        int h = 1;
        while (h < n / 3) h = 3 * h + 1;

        while (h >= 1) {
            // 将数组变成h有序
            for (int i = h; i < n; i++) {
                for (int j = i; j >= h && less(a[j], a[j - h]); j -= h) {
                    exch(a, j, j - h);
                }
            }
            assert isHsorted(a, h);
            h /= 3;
        }
        assert isSorted(a);
    }

    /**
     * 功能描述:v 是否小于 w
     *
     * @param v 待比较元素第一个元素
     * @param w 待比较元素第二个元素
     * @return boolean true:小于 false:大于等于
     * @author cakin
     * @date 2021/2/26
     */
    private static boolean less(Comparable v, Comparable w) {
        return v.compareTo(w) < 0;
    }

    /**
     * 功能描述:交换数组a中的第i个元素和第j个元素
     *
     * @param a 待交换的数组
     * @param i 数组下标
     * @param j 数组下标
     * @author cakin
     * @date 2021/2/26
     */
    private static void exch(Object[] a, int i, int j) {
        Object swap = a[i];
        a[i] = a[j];
        a[j] = swap;
    }

    /**
     * 功能描述:下标lo开始到下表hi结束的数组区间是否排好序
     *
     * @author cakin
     * @date 2021/2/26
     * @param a 数组
     * @return boolean true:排好序 false:没排好序
     */
    private static boolean isSorted(Comparable[] a) {
        for (int i = 1; i < a.length; i++)
            if (less(a[i], a[i - 1])) return false;
        return true;
    }

    /**
     * 功能描述:数组a是否基于步长h排序
     *
     * @author cakin
     * @date 2021/2/27
     * @param a 数组
     * @param h 步长
     */
    private static boolean isHsorted(Comparable[] a, int h) {
        for (int i = h; i < a.length; i++)
            if (less(a[i], a[i - h])) return false;
        return true;
    }

    /**
     * 功能描述:打印数组
     *
     * @author cakin
     * @date 2021/2/26
     * @param a 待打印的数组
     */
    private static void show(Comparable[] a) {
        for (int i = 0; i < a.length; i++) {
            StdOut.println(a[i]);
        }
    }

    /**
     * 功能描述:希尔排序测试
     *
     * @author cakin
     * @date 2021/2/27
     * @param args 命令行
     */
    public static void main(String[] args) {
        String[] a = StdIn.readAllStrings();
        Shell.sort(a);
        show(a);
    }
}

三 测试

F:\Algorithm\target\classes>java sort.Shell < tiny.txt
A
E
E
L
M
O
P
R
S
T
X

F:\Algorithm\target\classes>java sort.Shell < words3.txt
all
bad
bed
bug
dad
dim
dug
egg
fee
few
for
gig
hut
ilk
jam
jay
jot
joy
men
nob
now
owl
rap
sky
sob
tag
tap
tar
tip
wad
was
wee
yes
yet
zoo

四 说明

该算法达不到平方级别,在最坏的情况下,比较次数和N^1.5成正比。

五 希尔排序和插入排序比较

1 代码

package sort;

import common.StdOut;
import common.StdRandom;
import common.Stopwatch;

/**
* @ClassName: SortCompare
* @Description: 比较希尔排序和插入排序性能
* @Date: 2021/2/26
* @Author: cakin
*/
public class SortCompare {
    /**
     * 功能描述:算法alg使用的时间
     *
     * @author cakin
     * @date 2021/2/26
     * @param alg 算法名称
     * @param a 数组
     * @return double 算法使用时间
     */
    public static double time(String alg, Comparable[] a) {
        Selection selection = new Selection();
        Insertion insertion = new Insertion();
        Shell shell = new Shell();

        Stopwatch timer = new Stopwatch();
        if (alg.equals("Selection")) {
            selection.sort(a);
        }
        if (alg.equals("Insertion")) {
            insertion.sort(a);
        }
        if (alg.equals("Shell")) {
            shell.sort(a);
        }

        return timer.elapsedTime();
    }

    /**
     * 功能描述:使用 alg 将T个长度为N的数组排序
     *
     * @author cakin
     * @date 2021/2/26
     * @param alg 算法
     * @param N 数组长度
     * @param T 进行N次排序
     * @return 排序总时长
     */
    public static double timeRandomInput(String alg, int N, int T) {
        double total = 0.0;
        Double[] a = new Double[N];
        for (int t = 0; t < T; t++) {
            // 进行一次测试(生成一个数组并排序)
            for (int i = 0; i < N; i++) {
                a[i] = StdRandom.uniform();
            }
            total += time(alg, a);
        }
        return total;
    }

    /**
     * 功能描述:比较希尔排序和插入排序性能
     *
     * @author cakin
     * @date 2021/2/26
     * @param args 命令行
     */
    public static void main(String[] args) {
        String alg1 = args[0];
        String alg2 = args[1];
        int N = Integer.parseInt(args[2]);
        int T = Integer.parseInt(args[3]);
        double t1 = timeRandomInput(alg1, N, T); // alg1的总时间
        double t2 = timeRandomInput(alg2, N, T); // alg2的总时间
        StdOut.printf("For %d random Doubles\n  %s is", N, alg1);
        StdOut.printf(" %.1f times faster than %s\n", t2 / t1, alg2);
    }
}

2 测试

F:\Algorithm\target\classes>java sort.SortCompare Shell Insertion  1000 100
For 1000 random Doubles
  Shell is 1.4 times faster than Insertion

F:\Algorithm\target\classes>java sort.SortCompare Shell Insertion  1000 100
For 1000 random Doubles
  Shell is 3.5 times faster than Insertion

F:\Algorithm\target\classes>java sort.SortCompare Shell Insertion  1000 100
For 1000 random Doubles
  Shell is 7.1 times faster than Insertion

F:\Algorithm\target\classes>java sort.SortCompare Shell Insertion  1000 100
For 1000 random Doubles
  Shell is 6.2 times faster than Insertion

F:\Algorithm\target\classes>java sort.SortCompare Shell Insertion  1000 100
For 1000 random Doubles
  Shell is 3.9 times faster than Insertion

F:\Algorithm\target\classes>java sort.SortCompare Shell Insertion  1000 100
For 1000 random Doubles
  Shell is 6.5 times faster than Insertion

 

标签:sort,Shell,数组,int,param,希尔,Insertion,排序
来源: https://blog.csdn.net/chengqiuming/article/details/114184392