1. 程式人生 > >希爾排序---改良的直接插入排序

希爾排序---改良的直接插入排序

希爾排序是對直接插入排序的改良,也是衝破時間複雜度為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");
    }
}