數據結構之希爾排序(五)

排序思路:我們設置一個步長,然後我們根據這個步長進行劃分子序列,得到子序列1,子序列2….,然後我們對每個子序列進行直接插入排序,我們也知道當整個數列基本有序的時候使用直接插入排序的效率是非常高的。然後我們縮小步長,則我們劃分的子序列的個數越來越少,我們每個子序列中的數據越來越多,則我們基本有序的數據就越來越多,直到我們的增量爲1時,我們對整個已經基本有序的序列採用一次直接插入排序,則我們的排序結束。
這裏寫圖片描述

直接實現:

private static void shellsort(int[] arr, int length) {
        // 初始設置增量爲數組長度的一半,則我們的每個子序列只有兩個數據
        // 我們每次的排序都是根據步長來確定的,而我們的步長每次排序完成後都要改變,直到步長爲1,我們這裏採用的步長長度每次爲一半
        // 在上面設置了步長以後,則我們的待排序數組已經被分成若干個子序列了,則我們對每個子序列進行直接插入排序
        for (int gap = length / 2; gap >= 1; gap = gap / 2) { 
            int m;
            // 我們在這裏設置一個循環,這個循環我們用於對每個子序列的起點進行設置,每個子序列的起點都是在0到gap之間的
            // 這樣我們就可以把子序列抽離出來,分別是m,m+gap,m+gap+gap...,則我們對這個序列進行直接插入排序
            for (m = 0; m < gap; m++) { 
                int i;
                int temp;
                for (i = m + gap; i < length; i = i + gap) { // 我們對這個序列進行直接插入排序
                    int j = i; // 在這裏我們單獨定義一個j出來,不能直接對i進行操作,直接操作i以後,i會發生變化,則我們的遍歷對象不準確了
                    while (j != m) {
                        if (arr[j] <= arr[j - gap]) { // 這個子序列相鄰元素之間的距離不再是1,而是gap
                            temp = arr[j - gap];
                            arr[j - gap] = arr[j];
                            arr[j] = temp;
                        }
                        j = j - gap; // 下標跳轉到下一個元素
                    }
                }
            }
        }

        for (int i = 0; i < 15; i++) {
            System.err.printf("%d ", arr[i]);
        }
    }

算法分析: 希爾排序原理:設置間隔變量,將數組進行分組,組內排序,然後縮小間隔變量,直至間隔變量爲1(結束條件)
1. 希爾排序的空間佔用率爲O(1),
2. 希爾排序在平均情況下時間複雜度爲O(nlogn),最好情況下爲O(n的平方)
下面來分析原始的希爾排序的時間複雜度,初始步長d=n/2,下一次步長d=d/2
第一次比較次數,每組2個元素:1*n/2
第二次比較次數,每組4個元素:最壞(1+2+3)*n/4
第三次比較次數,每組8個元素:最壞(1+2+3+……+7)*n/8
2^(m-1) ( m 表示第幾次比較 ) < 每組最壞的元素比較次數 < 2^(m)
例子 :2^2 < 7 < 2^3 (第 3 次比較,最後一個元素的最差比較次數 )
累加求極限,得到算法複雜度小於 O(n^2) 。
3.希爾排序是一種不穩定的內部排序算法

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