數據結構與算法系列——排序(2)_直接插入排序

1. 工做原理(定義)

  直接插入排序(Straight Insertion Sort)的基本思想是:把n個待排序的元素當作爲一個有序表和一個無序表。開始時有序表中只包含1個元素,無序表中包含有n-1個元素,排序過程當中每次從無序表中取出第一個元素,將它插入到有序表中的適當位置,使之成爲新的有序表,重複n-1次可完成排序過程。html

  【經過構建有序序列,對於未排序數據,在已排序序列中從後向前掃描,找到相應位置並插入。】java

2. 算法步驟

    設數組爲a[0…n]。 git

  1. 將原序列分紅有序區和無序區。a[0…i-1]爲有序區,a[i…n] 爲無序區。(i從1開始) 
  2. 從無序區中取出第一個元素,有序區中從後向前掃描查找要插入的位置索引j。 
  3. 將a[j]到a[i-1]的元素後移,並將a[i]賦值給a[j],使R[0 … i]變爲新的有序區。【增量法】
  4. 重複步驟2~3,直到無序區元素爲0。github

  

3. 動畫演示

1. 最好的狀況

  

  最好的狀況就是,待排關鍵字序列的順序自己就是有序的(即從小到大的方式排列),這樣的話,在排序進行比較的時候每次只比較一次就好了,那麼總的「比較」次數爲:n-1。【
算法

  在直接插入排序算法中每次都須要提取無序區中的關鍵字,即tmp=R[i];同時還須要把關鍵字插入到有序區中合適的位置,即R[j].key = temp.key 。那麼總的移動次數爲:2(n−1)數組

  所以在最好的狀況下,直接插入排序算法的時間複雜度是:O(n)數據結構

2. 最壞的狀況

  

  對於最壞的狀況就是,咱們的需求是按從小到大的方式排序,可是關鍵字序列中的順序是逆序的(即從大到小的方式排列),在這種狀況下,每次都要把有序區中的全部關鍵字都比較一次,總的比較次數爲: n(n−1)/2。【性能

  在最壞的狀況下,每次都要把關鍵字插入最前面的位置(即每次都要把有序區中全部關鍵字日後移動),那麼總的移動次數爲: (n−1)(n+4)/2。【學習

  所以在最壞的狀況下,直接插入排序算法的時間複雜度是O(n^2)動畫

3. 普通狀況

  

  總的平均比較和移動次數大概是:O(n^2)

  也就是說,直接插入排序算法的平均時間複雜度仍是O(n^2),從穩定性來講,直接插入排序是一個穩定排序

4. 性能分析

1. 時間複雜度

  (1)順序排列時,只需比較(n-1)次,插入排序時間複雜度爲O(n);
  (2)逆序排序時,需比較n(n-1)/2次,插入排序時間複雜度爲O(n^2);
  (3)當原始序列雜亂無序時,平均時間複雜度爲O(n^2)。

2. 空間複雜度

  插入排序過程當中,須要一個臨時變量temp存儲待排序元素,所以空間複雜度爲O(1)。

3. 算法穩定性 

  插入排序是一種穩定的排序算法。

4. 初始順序狀態

   大部分元素有序時較好

  1. 比較次數:有關
  2. 移動次數:有關
  3. 複雜度:    有關
  4. 排序趟數:無關

4. 歸位

  不能歸爲,好比最後一個數爲最小值,那麼全部的值都未在最終的位置。

5. 優勢

  1.  穩定。
  2. 相對於冒泡排序與選擇排序更快。
  3. 大部分元素有序時好。

5. 算法改進

  1. 二分插入排序(折半插入排序 OR 拆半插入排序),採用折半查找方法。 

 直接插入排序算法在查找比較的過程當中採用的是順序查找;折半插入排序算法在查找比較的過程當中是採用折半查找的,所以折半插入排序的性能略高一些。

  2. 希爾排序,也稱遞減增量排序算法,是插入排序的一種更高效的改進版本。但希爾排序是非穩定排序算法。

   插入排序在對幾乎已經排好序的數據操做時,效率高,便可以達到線性排序的效率,但插入排序通常來講是低效的,由於插入排序每次只能將數據移動一位。

6. 具體代碼

import java.util.Arrays; public class InsertSort{ // 直接插入排序
    public int[] insertSort(int[] sourceArray) { // 對 arr 進行拷貝,不改變參數內容
        int[] arr = Arrays.copyOf(sourceArray, sourceArray.length); // 從下標爲1的元素開始選擇合適的位置插入,由於下標爲0的只有一個元素,默認是有序的
        for (int i = 1; i < arr.length; i++) { // 記錄要插入的數據
            int tmp = arr[i]; // 從已經排序的序列最右邊的開始比較,找到比其小的數
            int j = i; while (j > 0 && tmp < arr[j - 1]) {//等於的時候再也不減了,保證了穩定性
                arr[j] = arr[j - 1]; j--; } // 存在比其小的數,插入
            if (j != i) { arr[j] = tmp; } } return arr; } }

7. 參考網址

  1. 數據結構基礎學習筆記目錄
  2. 排序算法系列之直接插入排序
  3. https://visualgo.net/en/sorting
  4. https://www.runoob.com/w3cnote/insertion-sort.html
  5. https://github.com/hustcc/JS-Sorting-Algorithm
相關文章
相關標籤/搜索