1. 程式人生 > >演算法(3) 希爾排序 java

演算法(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) + "毫秒");
    }