排序算法(四):希尔排序

一、排序原理

希尔排序是插入排序的一种,又称为‘缩小增量排序’,是插入排序算法的一种更高效的改进版本。

1. 选定一个增长量h,按照增长量h对数据进行分组。

2. 对分好的每一组数据完成插入排序。

3. 减少增长量,最小减为1,重复第二步操作。

增长量h的确定规则:增长量h的值为一固定的规则,我们采用以下规则:

int h = 1;
while(h<数组的长度/2) {
    h = 2h+1;
}
//h的减小规则为:
h = h/2;

二、代码实现

import java.util.Arrays;

/**
 * 希尔排序
 */
public class ShellSort {

    public static void main(String[] args) {
        Integer[] arr = {4, 5, 3, 9, 2, 1};
        sort(arr);
        System.out.println(Arrays.asList(arr).toString());
    }

    public static void sort(Comparable[] a) {
        /**
         * int h = 1;
         * while(h<数组的长度/2) {
         *     h = 2h+1;
         * }
         * //h的减小规则为:
         * h = h/2;
         */
        // 根据数组a的长度,确定增长量h的初始值
        int h = 1;
        while (h < a.length / 2) {
            h = 2 * h + 1;
        }
        // 进行希尔排序
        while (h >= 1) {
            // 找到待插入的元素,并把待插入的元素插入到有序数列中
            for (int i = 0; i < a.length; i++) {
                for (int j = i; j > h; j -= h) {
                    // 待插入的元素为a[j],比较a[j]和a[j-h]
                    if (greater(a[j - h], a[j])) {
                        // 交换元素
                        exch(a, j - h, j);
                    } else {
                        // 已经找到合适的位置
                    }

                }
            }

            // 减少h的值
            h = h / 2;
        }

        for (int i = 0; i < a.length; i++) {
            for (int j = i; j > 0; j--) {
                // 比较索引j处的值和索引j-1处的值,如果j-1处的值比j处的值大,则交换。如果不大,则证明找到合适的位置了,退出本次循环
                if (greater(a[j - 1], a[j])) {
                    exch(a, j, j - 1);
                } else {
                    break;
                }
            }
        }
    }

    private static boolean greater(Comparable i, Comparable j) {
        return i.compareTo(j) > 0;
    }

    public static void exch(Comparable[] a, int i, int j) {
        Comparable temp = a[i];
        a[i] = a[j];
        a[j] = temp;
    }
}

运行结果:

[1, 2, 3, 4, 5, 9]

三、时间复杂度分析

1、希尔排序的优化点

希尔排序是插入排序的优化版本,利用的是插入排序的两个特点:

1).在大多数元素已经有序的情况下,插入排序的工作量较小

这个结论很明显,如果一个数组大部分元素都有序,那么数组中的元素自然不需要频繁地进行比较和交换。

2).在元素数量较少的情况下,插入排序的工作量较小

这个结论更加显而易见,插入排序的工作量和n的平方成正比,如果n比较小,那么排序的工作量自然要小得多。

2、希尔排序的时间复杂度

时间复杂度为:O(n^(1.3—2))

空间复杂度:O(1) 

稳定性:不稳定

 

 

posted @ 2020-05-17 09:47  灰色飘零  阅读(669)  评论(0)    收藏  举报