算法(3) 希尔排序 java

简介:希尔排序的实质其实是分组插入排序,再通俗的讲就是缩小增量排序,是一种比O(N^2)要好的排序算法,当然,是比不上O(NlgN)的算法.

原理:将整个待排元素序列分割成若干个子序列(由相隔某个增量值gap的元素组成),再分别对每个子序列进行快速插入排序,然后减少gap再进行快速插入排序,gap减少到足够小,最好是减少到1的时候进行最后一次快速插入排序(gap1的时候,相当于整个数组是一个子序列,但是经过前面的若干次重排,整个数组基本有序,最后进行一次微排即可),此时,整个数组就是有序的.因为快速插入排序在数组为基本有序时,效率是很高的,比选择排序和插入排序要高效的多,当然在gap的减少策略上,不同的减少策略也会带来不一样的效率.

原始数组如下:


增量计算方式gap = length / 2    采用gap = gap / 2 

gap = 10 / 2 = 5

按照相隔为5的原则 将整个数组按照以下顺序分割为了5,每组分别进行快速插入排序.这样在这五组中就有序了


gap = 5 / 2 = 2

  按照相隔为2的原则,将整个数组分割为了2,再次进行快速插入排序.


gap = 2 / 2 = 1

即对数组进行一次快速插入排序即可.结果如下


Java代码如下:

public static void sort(int[] arr) {
		long start = System.currentTimeMillis();
		int i, j, gap;
		for (gap = arr.length / 2; gap > 0; gap = gap / 2) {// 控制分组
			for (i = 0; i < gap; i++) {//控制组群排序
				for (j = i + gap; j < arr.length; j += gap) {// 控制单组排序
					int tmp = arr[j];
					int k = j - gap;
					while (k >= 0 && arr[k] > tmp) {
						arr[k + gap] = arr[k];
						k = k - gap;
					}
					arr[k + gap] = tmp;
				}
			}
		}
		System.out.println("time=" + (System.currentTimeMillis() - start) + "毫秒");     
	}
经过优化的增量序列如Hibbard经过复杂证明可使得最坏时间复杂度为O(n3/2)

public static void betterSort(int[] arr){
		long start = System.currentTimeMillis();
        int n = arr.length;

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

        while (h >= 1) {

            // h-sort the array
            for (int i = h; i < n; i++) {                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                        

                // 对 arr[i], arr[i-h], arr[i-2*h], arr[i-3*h]... 使用插入排序
                int e = arr[i];
                int j = i; 
                for ( ; j >= h && e < arr[j - h] ; j -= h)
                    arr[j] = arr[j-h];
                arr[j] = e;
            }

            h /= 3;
        }
        System.out.println("betterSort=" + (System.currentTimeMillis() - start) + "毫秒");
    }





猜你喜欢

转载自blog.csdn.net/weixin_37699212/article/details/79003395
今日推荐