排序(二) 十分鍾讓你掌握插入排序


前言:這里將主要介紹的是直接插入排序和改進后的插入排序也稱為希爾排序

 

直接插入排序 (時間復雜度為O(N^2))

介紹:

插入排序(Insertion Sort)的算法描述是一種簡單直觀的排序算法。它的工作原理是通過構建有序序列,對於未排序數據,在已排序序列中從后向前掃描,找到相應位置並插入。插入排序在實現上,通常采用in-place排序(即只需用到O(1)的額外空間的排序),因而在從后向前掃描過程中,需要反復把已排序元素逐步向后挪位,為最新元素提供插入空間。

 

方式一步驟

1.從第一個元素開始,該元素可以認為已經被排序
2.取出下一個元素,在已經排序的元素序列中從后向前掃描
3.如果該元素(已排序)大於新元素,將該元素移到下一位置
4.重復步驟3,直到找到已排序的元素小於或者等於新元素的位置
5.將新元素插入到該位置中
6.重復步驟2

 

只有文字的描述還是略顯的不太清晰,老規矩看圖:

 

 

實現的源代碼如下:

void InsertSort(T1 * arr, size_t size)    //傳入的參數是數組的首地址,數組的大小
{
    assert(arr);
    for (int i = 1; i < size; ++i)     
    {
        int end = i - 1;
        T1 tmp = arr[i];
        while (end >= 0 && arr[end] > tmp)   //end >= 0 確保的是上圖中的紅色箭頭一直指向數組的有效地址,arr[end] > tmp 代表箭頭指向的數大於圓圈中的數
        {
            arr[end + 1] = arr[end];
            --end;
        }
        arr[end + 1] = tmp;
    }
}

 

方式二:(是在方式一的基礎上進行了一些優化)

 

思想是這樣子滴:

 

源代碼如下:

void _Insert(int* arr, int size)
{
    assert(arr);
    for (int i = 1; i < size; ++i)
    {
        for (int end = i - 1; end >= 0; --end)
        {
            if (arr[end] > arr[end + 1])      //如果說,發現后面的比前面的小說明需要進行交換了
                swap(arr[end], arr[end + 1]);
            else 
                break;          //否則說明 i之前的序列已經是有序的了
        }
    }
}

 

 

 

希爾排序:(時間復雜度為 O(N^1.3))

介紹:希爾排序的實質就是分組插入排序,該方法又稱縮小增量排序,因DL.Shell於1959年提出而得名。

基本思想:先將整個待排元素序列分割成若干個子序列(由相隔某個“增量”的元素組成的)分別進行直接插入排序,然后依次縮減增量再進行排序,待整個序列中的元素基本有序(增量足夠小)時,再對全體元素進行一次直接插入排序。因為直接插入排序在元素基本有序的情況下(接近最好情況),效率是很高的,因此希爾排序在時間效率上比前兩種方法有較大提高

 

如圖:

 

 

源代碼:

void _ShellSort(int * arr, int size)
{
    assert(arr);
    int gap = size;
    while (gap > 1)
    {
        gap = gap / 3 + 1;     //(調整步長)庫中的步長是這樣計算滴,當步長為 1 時其實就是一個直接插入排序
        for (int i = gap; i < size; ++i)
        {
            int end = i - gap;
            int tmp = arr[i];
            while (end >= 0 && arr[end] > tmp)
            {
                arr[end + gap] = arr[end];
                end -= gap;
            }
            arr[end + gap] = tmp;
        }
    }
}

 

 

//與直接插入排序類似,改進后的希爾排序也可以這樣寫:

void _ShellSort(int * arr, int size)
{
    assert(arr);
    int gap = size;
    while (gap > 1)
    {
        gap = gap / 3 + 1;     
        for (int i = gap; i < size; ++i)
        {
            for (int end = i - gap; end >= 0; end -= gap)
            {
                if (arr[end] > arr[end + gap])    //如果不滿足升序,則交換兩個數
                {
                    swap(arr[end], arr[end + gap]);
                }
                else     //否則就認為,i 所在組,在i之前的所有元素都已經是升序了
                {
                    break;
                }
            }
        }
    }
}

 

 

 

現在呢,插入排序寫的差不多的,你如果還有什么更好的想法、意見或者建議的,歡迎參與評論,跪求賜教~~

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM