切換
舊版
前往
大廳
主題

超日常排序法 插入排序法(Insertion sort)

魔化鬼鬼 | 2020-05-26 10:52:23 | 巴幣 4 | 人氣 398

    這篇來介紹的演算法是和前面介紹的泡沫排序、選擇排序同時間複雜度的排序法O(n^2)- Insertion sort,又叫插入排序。以下的gif就是其運作方式:

    老慣例,依舊從說文解字開始,插入排序基本上就是從排好的數列中,把值給插進去,類似你打牌時候會排牌一樣,所以標題才說「超日常」,假設你手上的牌是:
(暫且不考慮花色)
1 6 9 J Q K

當你拿到 8 時,你會找到6跟9中間可以插,然後把牌插進去,變成:
1 6 8 9 J Q K

    換成程式的話主要有兩個動作,插入、後移,後移什麼?插入前要先把整體後移,然後才能把值插進去。所以想實作的可以先看到這邊就停下來,往這兩個方向去想並實作了。下面是例子:

如果我們要把值從小排到大
假設我們有一個長度為6的陣列
arr[6] = {6,5,8,12,9,11}

第一輪
從第二個開始掃
先宣告一個整數 temp
然後把第二個值存到temp裡面

5 < 6,所以開始往前看
只要比5大的通通都往後移
找到適合的位置後(也就是arr[0]),把temp插到arr[0]裡面
此輪結果
5 6 8 12 9 11

第二輪
從第三個開始掃
把第三個值存到temp裡面
6 < 8
所以就不變
此輪結果
5 6 8 12 9 11

第三輪
從第四個開始掃
把第四個值存到temp裡面
8 < 12
所以就不變
此輪結果
5 6 8 12 9 11

第四輪
從第五個開始掃
把第五個值存到temp裡面
9 < 12
所以就不變
此輪結果
5 6 8 9 12 11

第五輪
從第六個開始掃
把第六個值存到temp裡面
12 > 11,所以開始往前看
只要比11大的都往後移
找到適合的位置後(也就是arr[4]),把temp插到arr[4]裡面
此輪結果
5 6 8 9 11 12

    這樣就完成了!很簡單吧!

    一般來說,插入排序在小型的陣列中,運作效率會是最好的,或者更精確地說,插入排序在幾乎要排列好的數據中效率是最好的,接近O(n)。所以在Python的排序法TimSort中,其實也混用了插入排序,讓它在某些情況下可以優化整體,至於細節我就不清楚了,想了解的可以去維基看看。

以下是我用java寫的程式碼
純迴圈版:
public static void insertionSort(int[] arr, int beginI, int endI){
        if(beginI == endI){
            return;
        }
        int temp;
        int j;
        for (int i = beginI+1; i < endI+1; i++) {
            temp = arr[i];
            j = i-1;
            while(j>=0 && temp < arr[j] ){
                arr[j+1] = arr[j];
                j--;
            }
            arr[j+1] = temp;
        }
    }

遞迴版:
public static void insertionSort(int[] arr, int beginI, int endI){
        if(beginI == endI){
            return;
        }

        insertionSort(arr, beginI, endI-1);

        int temp;
        int j = endI;
        temp = arr[endI];
        while(j-1 >= beginI && temp < arr[j-1] ){
            j--;
            arr[j+1] = arr[j];
        }
        arr[j] = temp;
    }

創作回應

相關創作

更多創作