天天看点

希尔排序java实现

思想

shell排序是对直接插入排序的改进,我们已经知道,直接插入排序的复杂度受本身序列的有序程度影响,当数组已经有序,则每次查找插入的位置时间O(1),总的复杂度O(n),而当逆序对较多时,或者全部全部逆序时,复杂度为O(n^2)。所以希尔排序的思想是先优化子序列的有序程度,慢慢增大序列长度,最后对整个数组排序。

步骤

1、确定增量序列

2、按照增量序列分组,对每组进行直接插入排序(以第一个子序列的第二元素开始,向前面寻找更大的元素,没有则停下来)

3、重复1,直到增量为1

代码实现

class ShellSort{
    public static void main(String[] args) {
        int[] a={100,50,9,3, 4, 10, 3, 6, 7, 4, 1, 2};
        int n=a.length;
        int gap=n;
        while (gap>1){//最小间隔是1
            gap=gap/2;//最优增量缩减序列选择不确定,1/2是希尔建议的方式
            //其实下面的跟直接插入排序差不多,区别是开始索引是gap,查找间隔是gap
            for (int i=gap;i<n;i++){
                int k=a[i];//新元素
                int start=i-gap;//待比较元素
                while (start>=0&&a[start]>k){//大的往后移
                    a[start+gap]=a[start];
                    start-=gap;//间隔是gap
                }
                a[start+gap]=k;//把k放到合适的位置
            }
        }
        for (int i:a){
            System.out.print(i+" ");
        }
    }
}
           

算法分析

注意我们在每次对每个分组排序的时候不是分别对每个组分开排序,而是仍然从前往后扫描,那么显然,我们每次直接插入排序的key从每次的第一个子序列的第二个元素开始(与直接插入排序同理),然后挨个往后走,每个元素属于哪个组,我们就把它在其所在组进行直接插入排序。有点绕,仔细想想就好啦。

平均时间复杂度:o(N1.3),大量数据研究表明在o(N1.3)附近,事实上也不是严格论证的结果。

最好时间复杂度:仍然和增量序列的选取有关。

最坏时间复杂度:o(N^2)。

空间复杂度:o(1)只有常数个辅助变量。

稳定性:不稳定,例如待排序列(3,2,2,1),取d=2时,显然就能看出是不稳定的

继续阅读