1. 程式人生 > 其它 >演算法03 七大排序之:直接插入排序和希爾排序

演算法03 七大排序之:直接插入排序和希爾排序

上一篇總結了直接選擇排序和堆排序,這一篇要總結的是插入排序中的直接插入排序和希爾排序,我們主要從以下幾點進行總結。

1、直接插入排序及演算法實現

2、希爾排序及演算法實現

3、直接插入排序PK希爾排序

1、直接插入排序及演算法實現

什麼是直接插入排序呢?直接插入排序的基本思想是:每次從無序序列中取出第一個元素插入到已經排好序的有序序列中,從而得到一個新的,數量加1的有序序列。

1-1、示意圖

下面是直接插入排序的圖解說明。

1-2、程式碼

下面是直接插入排序的演算法實現程式碼。

InsertSort.java

public class InsertSort {
    public static void main(String[] args) {
        int[] list = {90, 10, 20, 50, 70, 40, 80, 60, 30, 52};
        System.out.println("************直接插入排序************");
        System.out.println("排序前:");
        display(list);
        System.out.println("");

        System.out.println("排序後:");
        insertSort(list);
        display(list);
    }

    /**
     * 直接插入排序演算法
     */
    public static void insertSort(int[] list) {
        // 從無序序列中取出第一個元素 (注意無序序列是從第二個元素開始的)
        for (int i = 1; i < list.length; i++) {
            int temp = list[i];
            int j;
            // 遍歷有序序列
            // 如果有序序列中的元素比臨時元素大,則將有序序列中比臨時元素大的元素依次後移
            for (j = i - 1; j >= 0 && list[j] > temp; j--) {
                list[j + 1] = list[j];
            }
            // 將臨時元素插入到騰出的位置中
            list[j + 1] = temp;
        }
    }
    
    /**
     * 遍歷列印
     */
    public static void display(int[] list) {
        System.out.println("********展示開始********");
        if (list != null && list.length > 0) {
            for (int num :
                    list) {
                System.out.print(num + " ");
            }
            System.out.println("");
        }
        System.out.println("********展示結束********");
    }
}

測試結果:

2、希爾排序及演算法實現

 希爾排序是直接插入排序的一種更高效的改進版本,又稱為“縮小增量排序”。

2-1、示意圖

2-2、程式碼

ShellSort.java 

public class ShellSort {
    public static void main(String[] args) {
        int[] list = {8, 9, 1, 7, 2, 3, 5, 4, 6, 0};
        System.out.println("************希爾排序************");
        System.out.println("排序前:");
        display(list);
        System.out.println("");

        System.out.println("排序後:");
        shellSort(list);
        display(list);
    }

    /**
     * 希爾排序演算法
     */
    public static void shellSort(int[] list) {
        // 取增量
        int gap = list.length / 2;

        while (gap >= 1) {
            // 無序序列
            for (int i = gap; i < list.length; i++) {
                int temp = list[i];
                int j;

                // 有序序列
                for (j = i - gap; j >= 0 && list[j] > temp; j = j - gap) {
                    list[j + gap] = list[j];
                }
                list[j + gap] = temp;
            }

            // 縮小增量
            gap = gap / 2;
        }
    }

    /**
     * 遍歷列印
     */
    public static void display(int[] list) {
        System.out.println("********展示開始********");
        if (list != null && list.length > 0) {
            for (int num :
                    list) {
                System.out.print(num + " ");
            }
            System.out.println("");
        }
        System.out.println("********展示結束********");
    }
}

測試結果:

3、直接插入排序PK希爾排序

既然希爾排序是直接插入排序的改進版,我們就來測試一下希爾排序是否真的比直接插入排序更快? 

程式碼:

InsertSortPkShellSort.java

public class InsertSortPkShellSort {
    public static void main(String[] args) {
        testInsertSort();
        testShellSort();
    }

    /**
     * 測試直接插入排序耗費的時間
     */
    public static void testInsertSort() {
        int[] list = new int[10000];
        for (int i = 0; i < 10000; i++) {
            list[i] = (int) (Math.random() * 100000);
        }

        // 直接插入排序
        long start = System.currentTimeMillis();
        InsertSort.insertSort(list);
        long end = System.currentTimeMillis();
        System.out.println("直接插入排序耗費的時間:" + (end - start));
        display(list);
    }

    /**
     * 測試希爾排序耗費的時間
     */
    public static void testShellSort() {
        int[] list = new int[10000];
        for (int i = 0; i < 10000; i++) {
            list[i] = (int) (Math.random() * 100000);
        }

        // 希爾排序
        long start = System.currentTimeMillis();
        ShellSort.shellSort(list);
        long end = System.currentTimeMillis();
        System.out.println("希爾排序耗費的時間:" + (end - start));
        display(list);
    }

    /**
     * 遍歷列印前10個數
     */
    public static void display(int[] list) {
        System.out.println("********排序之後的前10個數start********");
        if (list != null && list.length > 0) {
            for (int i = 0; i < 10; i++) {
                System.out.print(list[i] + " ");
            }
            System.out.println("");
        }
        System.out.println("********排序之後的前10個數end**********");
        System.out.println("");
    }
}

測試結果:

從測試結果可以看出,希爾排序比直接插入排序更快。