【Java數據結構與算法】希爾排序

希爾排序

基本介紹

希爾排序是希爾(DonaldShell)於1959年提出的一種排序算法。希爾排序也是一種插入排序,它是簡單插入排序經過改進之後的一個更高效的版本,也稱爲縮小增量排序

插入排序文章:插入排序

希爾排序法基本思想:
希爾排序是把記錄按下標的一定增量分組,對每組使用直接插入排序算法排序;隨着增量逐漸減少,每組包含的關鍵詞越來越多,當增量減至1時,整個文件恰被分成一組,算法便停止。

希爾排序算法的過程

原始數組:8 9 1 7 2 3 5 4 6 0

初始增量 gap = length / 2 = 5,意味着整個數組被分爲5組,[8,3] [9,5,] [1,4] [7,6] [2,0]

對這5組分班進行直接插入排序,結果如下,可以看到,像3,5,6這些小元素,都被調到了前面,然後縮小增量gap = 5 / 2 = 2,數組被分爲 2 組 [3,1,0,9,7] [5,6,8,4,2]

進行一輪之後:3 5 1 6 0 8 9 4 7 2

對以上2組再分班進行直接插入排序,結果如下,可以看到,此時整個數組的有序成都更進一步,再縮小增量gap = 2 / 2 = 1,此時,整個數組爲1組[0,2,1,4,3,5,7,6,9,8]

又進行一輪之後:0 2 1 4 3 5 7 6 9 8

經過上面的“宏觀調控”,整個數組的有序化程度成果喜人。此時,僅僅需要對以上數列簡單微調,無序大量移動操作即可完成整個數組的排序。

最終結果: 0 1 2 3 4 5 6 7 8 9

代碼實現交換法(不推薦使用)

package sort;

import java.text.SimpleDateFormat;
import java.util.Date;

public class ShellSort {
    public static void main(String[] args) {

        //int[] arr1 = {8,9,1,7,2,3,5,4,6,0};
        //測試希爾排序速度,給80000個數據,測試
        //創建一個80000個隨機的數組
        int[] arr = new int[80000];
        for (int i = 0;i < 80000;i ++) {
            //會生成一個[0,8000000]的數
            arr[i] = (int)(Math.random() * 8000000);
        }
        //System.out.println("最開始的數組爲:" + Arrays.toString(arr));
        Date date1 = new Date();
        SimpleDateFormat simpleDateFormat1 = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        String date1Str = simpleDateFormat1.format(date1);
        System.out.println("排序前的時間:" + date1Str);
        //測試希爾排序
        shellSort(arr);
        Date date2 = new Date();
        String date2Str = simpleDateFormat1.format(date2);
        System.out.println("排序後的時間:" + date2Str);
    }
    public static void shellSort(int[] arr) {
        int temp = 0;
        //設置每次的步長,如第一次分爲五組,則步長爲5
        for (int gap = arr.length / 2;gap > 0;gap /= 2) {
            for (int i = gap;i < arr.length;i ++) {
                //遍歷每組的元素(gap組,每組**個元素,步長gap)
                for (int j = i - gap;j >= 0;j -= gap) {
                    //如果前面的數大於後面的數,則交換位置
                    if (arr[j] > arr[j + gap]) {
                        temp = arr[j];
                        arr[j] = arr[j + gap];
                        arr[j + gap] = temp;
                    }
                }
            }
        }
    }
}

不推薦原因:未使用到插入排序的思想,而是使用的冒泡排序思想,導致運行速度負提示。

代碼實現移動法(推薦使用)

package sort;

import java.text.SimpleDateFormat;
import java.util.Date;

public class ShellSort {
    public static void main(String[] args) {
        //int[] arr1 = {8,9,1,7,2,3,5,4,6,0};
        //測試希爾排序速度,給80000個數據,測試
        //創建一個80000個隨機的數組
        int[] arr = new int[80000];
        for (int i = 0;i < 80000;i ++) {
            //會生成一個[0,8000000]的數
            arr[i] = (int)(Math.random() * 8000000);
        }
        //System.out.println("最開始的數組爲:" + Arrays.toString(arr));
        Date date1 = new Date();
        SimpleDateFormat simpleDateFormat1 = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        String date1Str = simpleDateFormat1.format(date1);
        System.out.println("排序前的時間:" + date1Str);
        //測試希爾排序
        shellSort(arr);
        Date date2 = new Date();
        String date2Str = simpleDateFormat1.format(date2);
        System.out.println("排序後的時間:" + date2Str);
    }
    public static void shellSort(int[] arr) {
        //設置每次的步長,如第一次分爲五組,則步長爲5
        for (int gap = arr.length / 2;gap > 0;gap /= 2) {
            //從第gap元素,逐個對其所在的組進行直接插入排序
            for (int i = gap;i < arr.length;i ++) {
                int j = i;
                int temp = arr[j];
                if (arr[j] < arr[j - gap]) {
                    while (j - gap >= 0 && temp < arr[j - gap]) {
                        //移動
                        arr[j] = arr[j - gap];
                        j -= gap;
                    }
                    //當退出循環之後,就給temp找到了插入的位置
                    arr[j] = temp;
                }
            }
        }
    }
}

筆記源自:韓順平數據結構與算法

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章