【一起學習排序演算法】4 插入排序

莫林發表於2018-11-30

本系列的文章列表和相關說明,請檢視序言。具體列表如下:
【一起學習排序演算法】0 序言
【一起學習排序演算法】1 演算法特性及大O記法
【一起學習排序演算法】2 氣泡排序
【一起學習排序演算法】3 選擇排序

也可以直接到github上檢視完整的文章和原始碼!

本篇為此係列第四篇。

插入排序 Insertion sort

原理

先看看Wikipedia的定義:

Insertion sort algorithm iterates, consuming one input element each repetition, and growing a sorted output list. Each iteration removes one element from the input data, finds the location it belongs within the sorted list, and inserts it there. It repeats until no input elements remain.

所以插入排序的思路就是:

  • 把列表分為兩個部分,一部分是已經排好序,一部分待排序。(這一點和選擇排序類似)
  • 初始將第一個元素作為有序子列為,然後每次迭代從有序序列中移除;然後將它插入到有序序列中的相應位置。
  • 重複以上步驟,直到到最後一個元素,則表示陣列有序。

圖示

可以通過動畫演示理解, 以下網上找的兩個動畫。如果你想操作不同的引數來演示,可以上這個網站visualgo.net動手試試。

圖示1

圖示2

程式碼實現

關於程式碼,README中程式碼只有實現演算法的函式,具體執行的程式碼,請檢視該目錄下的檔案。

程式碼如下:

const insertSort = (array) => {
    // 不修改原陣列
    const originValues = array.slice(); 

    // 初始將第一個元素指定為有序子列,從第2個元素開始插入,直到n-1元素 
    for (let i = 1; i < originValues.length; i++) {
        const currentValue = originValues[i];
        // 標記插入有序子列的位置
        let insertIndex = i;
        // 將當前元素從右到左與有序子列元素比較
        // 起始位置為當前元素前一個元素,即i-1,終止位置為0
        // 如果當前元素比該有序子列元素小,則該元素後移一位,並修改插入位置的遊標
        for (let j = i-1; j > -1 && currentValue < originValues[j]; j--) {
           originValues[j+1] = originValues[j];
           insertIndex = j;
        }
        // 插入指定位置
        originValues[insertIndex] = currentValue;
    }

    return originValues;
};
複製程式碼

以上就是直接插入排序的程式碼實現。總體來說還是比較簡單易懂,其實就類似於打撲克,不斷將撲克牌按順序插入指定位置。唯一可能有一點容易想不清楚的,就是有序子列的右移部分。想清楚一點,只要有序子列的該元素大於要插入的元素,該元素就要後移一位。

演算法分析

1. 時間複雜度
排序演算法中,兩個元素的比較次數是影響執行時間的首要因素。所以我們可以通過這個層面來評估。
最優複雜度
當陣列有序時,每一次迭代只有一次比較,所以總共有n-1次比較,複雜度為O(n)。
最差複雜度
當陣列逆序時,每一次都要比較整個有序子列,比較次數為:

T(n) = 1 + 2 + ... + n-1 = n*n/2
複製程式碼

所以,最差複雜度是O(n2)。

2. 穩定性
因為比較元素是,相同值不會交換,所以插入演算法是穩定的。

總結

本章節介紹了插入排序的實現。插入排序在思路上,和選擇排序還是有些類似的。插入排序的複雜度還是沒有突破O(n2)。
不過,上面的實現只是簡單的插入排序,還可以優化。就是在有序子列中找插入位置時,利用二叉查詢的方法,這樣複雜度可以到O(nlogn)。這裡先不做介紹。

參考

[1] 動畫演示
[2] tutorials point 教程
[3] Sorting Algorithms
[4] 凱耐基梅隆大學資料結構與演算法-排序演算法

相關文章