希爾排序也成爲「縮小增量排序」,其基本原理是,現將待排序的數組元素分紅多個子序列,使得每一個子序列的元素個數相對較少,而後對各個子序列分別進行直接插入排序,待整個待排序列「基本有序」後,最後在對全部元素進行一次直接插入排序。所以,咱們要採用跳躍分割的策略:將相距某個「增量」的記錄組成一個子序列,這樣才能保證在子序列內分別進行直接插入排序後獲得的結果是基本有序而不是局部有序。希爾排序是對直接插入排序算法的優化和升級。
所謂的基本有序,就是小的關鍵字基本在前面,大的基本在後面,不大不小的基本在中間,例如{2,1,3,6,4,7,5,8,9,}就能夠稱爲基本有序了。但像{1,5,9,3,7,8,2,4,6}這樣,9在第三位,2在倒數第三位就談不上基本有序。java
希爾排序的關鍵並非隨便分組後各自排序,而是將相隔某個「增量」的記錄組成一個子序列,實現跳躍式移動,使得排序的效率提升。須要注意的是,增量序列的最後一個增量值必須等於1才行。另外,因爲記錄是跳躍式的移動,希爾排序並非一種穩定的排序算法。
希爾排序最好時間複雜度和平均時間複雜度都是,最壞時間複雜度爲。//最好狀況即不須要交換數據算法
以數組{26, 53, 67, 48, 57, 13, 48, 32, 60, 50 }爲例,步長序列爲{5,2,1}
初始化關鍵字: [26, 53, 67, 48, 57, 13, 48, 32, 60, 50 ]數組
最後的排序結果:
13 26 32 48 48 50 53 57 60 67優化
先從array[0]開始,以incrementNum爲增量的進行直接插入排序,直到數組末尾,而後從array[1]開始重複:以incrementNum爲增量的進行直接插入排序; 而後從array[1]開始重複......一直到array[n]。spa
而後取一個小於上一步增量的新的增量(好比設置爲incrementNum/2),對前一個步驟的結果array進行遍歷,直接插入排序....code
再取小於上一步增量的新的增量,重複進行:遍歷,直接插入排序blog
直到新的增量小於1以後再退出循環排序
好比如今有數組{82 ,31 ,29 ,71, 72, 42, 64, 5,110} 第一次取增量設置爲array.length/2 = 4 先從82開始以4爲增量遍歷直到末尾,獲得(82,42) 排序獲得{42 ,31 ,29 ,71, 72, 82, 64, 5,110}。 而後從第二個數31開始重複上一個步驟,獲得(31,64) 排序獲得{42 ,31 ,29 ,71, 72, 82, 64, 5,110}....... 以4爲增量的遍歷完數組以後,獲得的結果是{42,31,5,71,72,82,64,29,110}圖片
而後從新區增量,這兒設定爲incrementNum/2 = 2,對{42 ,31,5,71,72,82,64,29,110}重複步驟1。 完事以後,在取新的增量,重複步驟1。 直到取到的增量小於1,退出循環。rem
好比有這麼一種狀況:對一個無序數組進行從小到大的排序,可是數組的最後一個位置的數是最小的,咱們要把它挪到第一個位置,其餘位置的都要日後移動,要是這個數組很是大,那麼直接插入排序的開銷就很是大。
package sort; import java.util.Arrays; /** * 希爾排序 * * @author TangJiang 2017年11月24日 下午4:51:37 * */ public class ShellSort { public static void ShellSortTest(int[] arr) { if (arr == null || arr.length <= 1) { return; } // 設置初始增量 int increase = arr.length / 2; while (increase >= 1) { for (int i = 0; i < arr.length; i++) { // 進行跳躍插入排序 for (int j = i; j < arr.length - increase; j = j + increase) { // 比較大小交換數據 if (arr[j] > arr[j + increase]) { int temp = arr[j]; arr[j] = arr[j + increase]; arr[j + increase] = temp; } } } // 設置新的增量 increase = increase / 2; } } public static void main(String[] args) { int[] a = { -1, 3, 6, 2, 6, 89, 3 }; ShellSortTest(a); // for (int i : a) { // System.out.println(i + ""); // } System.out.println(Arrays.toString(a)); } }