希爾排序---改良的直接插入排序
阿新 • • 發佈:2018-12-16
希爾排序是對直接插入排序的改良,也是衝破時間複雜度為O(n^2)的第一批演算法之一
基本思想:將插入排序並不是一次性排完,而是分組進行插入排序。如一共有count個元素,設步長step1為count / 2, 即每走count / 2個元素分為一組,一共可以分為step1組,分別對每一組進行插入排序,得到新陣列;此時縮短步長為step2=step1/2=count/2/2,每走step2個元素分為一組,一共可以分為step2個組,然後分別對每一組進行排序,得到新陣列;此時縮短步長為step3 = step2 / 2 = count / 2 / 2 / 2......直至步長為1,在最後對所有元素進行插入排序進行微調,下面是帶圖詳解
一個數組,共有count個元素(如下圖,圖是偷的哈哈)
那麼,初始步長為step = count / 2 = 5; 即步長為5,意思是每隔5步分為一組,一共有5組
分別對這五組元素進行排序,得到的結果為 3 5 1 6 0 8 9 4 7 2,並將步長縮短為step = step / 2 = 2;
此時步長為2,即每走兩步得到的元素為一組,共分為2組
對這2組的元素分別進行插入排序,得到結果為 0 2 1 4 3 5 7 6 9 8,並將步長縮短為step = step / 2 = 1;此時步長為1,即所有元素為一個組
再對這些元素進行插入排序,得到最後的結果~
程式碼實現:
package BetterSort; import java.util.Scanner; public class ShellSort { //是改良的直接插入排序 public static void main(String[] args) { Scanner sc= new Scanner(System.in); int array[] = new int[10]; //定義一個數組 System.out.println("請輸入要排序的數:"); for(int index = 0; index < 10; index++) { //用一個迴圈控制陣列的元素輸入 int i = sc.nextInt(); array[index] = i; } shellSort(array); printArray(array); } public static void shellSort(int[] array) { //設定初始步長,且當步長大於零時,每次迴圈將步長縮減為step/2 for(int step = array.length / 2; step > 0; step /= 2) { //設定陣列的初始下標為0,且每走step步得到的元素分為一組,並對這組數進行插入排序 //startIndex++是初始下標為1,然後繼續每走step步得到的元素分為一組,並對這組數進行插入排序 //直至下標為step-1時,遍歷完本次所有組的元素,並返回上層迴圈,改變步長 for(int startIndex = 0; startIndex < step; startIndex++) { insertSort(startIndex, array, step); } } } //插入排序 public static void insertSort(int startIndex, int[] array, int step) { int i = 0; int j = 0; int t = 0; for(i = startIndex + step; i < array.length; i += step) { //從下標為startIndex + step的第二個元素開始遍歷 int tmp = array[i]; //建立臨時變數,儲存需要插入的元素值 for(j = startIndex; j < i && tmp >= array[j]; j += step) { //找到應該插入的位置 } for(t = i; t > j; t -= step) { //將插入位置後面的元素後移一位 array[t] = array[t - step]; } array[j] = tmp; //將元素值插入最終位置 } } public static void printArray(int[] array) { //列印陣列元素的方法 for(int i = 0; i < array.length; i++) { System.out.print(array[i] + " "); } System.out.print("\n"); } }