【演算法】簡述插入排序法 Insertion Sort

假設第一個元素已經排序完成,之後第二個元素加進來後便會與前者元素比較,如果前者元素 > 第二個元素,便會將前者元素往後一個元素(而不是將現在正在比較的元素 replace 到前者元素,這點有些人會誤解)。第三個元素進來後也是會與第二個元素作比較,進而決定往前還是停留。以此類推。

簡單插入排序法 SOP 如下(大前提為當前比較元素的前面所有元素均假設排序完成):

  1. 從需要排序的清單中,取出第 k 個元素當作基準值(假設第一項已經排完了,所以要從陣列第二個開始找起)
  2. 與前面 n 個元素一次比較,如果前者元素比現在正在用來比較的元素還大,則將前者元素存入下一個索引值中。
  3. 直到遇到前者元素比當前用來比較的元素還小,那就將目前用來比較的元素放到前者元素的下一個位置中(previou + 1)。
  4. k = k+1 ,開始繼續拿下一個元素當作比較基準。

有些人會說如果把前者元素往後移動一個 index,那我們現在用來比較元素的那個 index 不就會被前者取代?對!沒錯,所以你需要在每次比較前先將當前用來比較的元素值存在一個暫時的新變數中,下面的程式將以 key 來存放當前正在比較的元素。

插入排序法的時間複雜度為 O(n^{2}),並且為穩定排列(意思就是當有兩個 2 的時候,縱使排列完成,兩個 2 的相對位置也是不變,原本在前面的 2 還是會在前面)

程式碼示範

C++

#include <iostream>
using namespace std;

//插入排序流程:逐一將原始資料加入已排序好資料中,並逐一與已排序好的資料作比較,找到對的位置插入
void insertionSort(int *arr, int length){
    int key,previous;
    
    // 依次加入數字作比較
    for(int i = 1 ; i < length ; i++){
        key = arr[i];
        previous = i - 1;
        
        // 當前一位數索引值 >= 0 (還在串列中) 以及當前索引值比 key 還大,則將 key 往前丟
        while(previous >= 0 && arr[previous] > key){
            // 把他往後丟一格
            arr[previous + 1] = arr[previous];
            previous--;
        }
        
        // 當前面比 key 值還小,那就在他下一個索引值停下放下
        arr[previous+1] = key;
    }
}

int main(){
    int arr[10] = {1,4,100,2,6,7,3,10,5,87};
    // 運用計算總大小/單個元素大小得出串列長度
    int length = sizeof(arr)/sizeof(arr[0]);

    for(int i = 0 ; i < length; i++) cout << arr[i] << " ";cout << endl;

    insertionSort(arr,length);

    for(int i = 0 ; i < length; i++) cout << arr[i] << " ";
    return 0;
}

輸出結果大概會是長這樣,第一行為排序前元素,第二行為排序後元素:

1 4 100 2 6 7 3 10 5 87 
1 2 3 4 5 6 7 10 87 100 

發佈留言

發佈留言必須填寫的電子郵件地址不會公開。 必填欄位標示為 *