1. 程式人生 > >排序之-----插入排序於希爾排序

排序之-----插入排序於希爾排序

插入排序

插入排序基本思想:每一步將一個元素的排序碼按照大小,插入到前面已經排好序的元素之中的合適位置,直到最後一個元素也插入了他之前的有序序列。

直接插入排序 將array[i] 插到已經有序的array[0] array[i] ….. array[i - 1]中 先儲存array[i]一個個比較 找到了位置後 將其他數均向後移動一個位置。 最後插入儲存好的元素。

直接插入排序在對待待排序列基本有序且規模不大時 比較好
時間複雜度在O(n) 與O(n ^ 2)之間 一般認為是O(n ^ 2)。 空間複雜度O(1)。

圖示:
這裡寫圖片描述

//直接插入排序   寫程式碼關鍵在於理解end的位置
template<class T> void InsertSort(T* arr, size_t n) { assert(arr && n > 0); size_t front = 0; for (; front < n - 1; ++front){ int end = front; //有序數列的最後一個是end T tmp = arr[end + 1]; while (end >= 0){ if (arr[end] > tmp){//比要插入的數字大就向後移
arr[end + 1] = arr[end]; --end; } else break; } //必要插入的數字小就讓它插在後面 arr[end +` 1] = tmp; } }

希爾排序

設待排序元素有n個,首先取一個整數gap < n作為間隔,將全部元素分為gap組,所有距離為gap的元素都在同一個組裡,然後對每一個組都進行插入排序。然後縮小增量,直到gap==1的時候整個序列都會變成有序的。希爾排序是直接插入排序的變形。

圖示:
這裡寫圖片描述

程式碼:

template<class T>
void ShellSort(T* arr, size_t n)
{
    assert(arr);
    int gap = n;
    while (gap > 1){
        gap = gap / 3 + 1;
        for (int front = 0; front < n - gap; front++){
            int end = front;
            T tmp = arr[end + gap];
            while (end >= 0){
                if (arr[end] > tmp){
                    arr[end + gap] = arr[end];
                    end -= gap;
                }
                else{
                    break;
                }
            }
            arr[end + gap] = tmp;
        }
    }
}

進行希爾排序的時候gap的選取很重要,決定了排序效率的高低,一般最開始設定gap為要排序的元素的個數,接下來gap按照gap=gap/3+1的趨勢進行變化。希爾排序的平均時間複雜度是在n^1.25到1.6n^1.25的範圍內。

希爾排序與插入排序的比較:

插入排序在什麼情況下效率最高呢???

如果當要排序的序列大致上接近於有序的時候,插入排序的效率最高,基本上接近O(N)。因為當資料基本上接近於有序的時候,元素向有序區插入的時候比較的次數會很少,同樣有序區元素向後移動的次數也是很少的。

####那麼插入排序在什麼情況下的效率最低呢???
如果當要排序的序列大致上接近於逆序的時候,插入排序的效率最低,基本上接近與O(N*N)。因為這時候每向有序區插入一個元素的時候,假設最極端的情況下要比較和移動的次數就是有序區的長度。這時候插入排序的效率就會很低。

針對於插入排序的最壞的情況,希爾排序對它進行了優化,希爾排序先對這組資料進行預排序(就是gap不為1的時候進行的分組排序),通過預排序就能將這組資料快速的接近於有序,這時候再使用插入排序效率就會提升上去。所以希爾排序的增量選擇就很重要,增量大額話會起不到預排序的效果,增量小的話效率又會降低。

如果當一組資料接近的有序的話,我們優先使用插入排序,效率高。如果當一組資料接近於逆序的話,我們使用希爾排序會更優。插入情況最好的情況就是希爾排序最壞的情況,因為這時候希爾排序的預排序起不到作用。插入排序最壞的情況則是希爾排序最高的情況,因為這時候預排序的效果是非常明顯的。