直接插入排序(Straight Insertion Sort)的基本思想是:把n個待排序的元素當作爲一個有序表和一個無序表。開始時有序表中只包含1個元素,無序表中包含有n-1個元素,排序過程當中每次從無序表中取出第一個元素,將它插入到有序表中的適當位置,使之成爲新的有序表,重複n-1次可完成排序過程。html
【經過構建有序序列,對於未排序數據,在已排序序列中從後向前掃描,找到相應位置並插入。】java
設數組爲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
最好的狀況就是,待排關鍵字序列的順序自己就是有序的(即從小到大的方式排列),這樣的話,在排序進行比較的時候每次只比較一次
就好了,那麼總的「比較」次數爲:n-1。【】
算法
在直接插入排序算法中每次都須要提取無序區中的關鍵字,即tmp=R[i];同時還須要把關鍵字插入到有序區中合適的位置,即R[j].key = temp.key 。那麼總的移動次數爲:2(n−1)。數組
所以在最好的狀況下,直接插入排序算法的時間複雜度是:O(n)。數據結構
對於最壞的狀況就是,咱們的需求是按從小到大的方式排序,可是關鍵字序列中的順序是逆序的(即從大到小的方式排列),在這種狀況下,每次都要把有序區中的全部關鍵字都比較一次,總的比較次數爲: n(n−1)/2。【】性能
在最壞的狀況下,每次都要把關鍵字插入最前面的位置(即每次都要把有序區中全部關鍵字日後移動),那麼總的移動次數爲: (n−1)(n+4)/2。【】學習
所以在最壞的狀況下,直接插入排序算法的時間複雜度是O(n^2)。動畫
總的平均比較和移動次數大概是:O(n^2)
也就是說,直接插入排序算法的平均時間複雜度仍是O(n^2),從穩定性來講,直接插入排序是一個穩定排序。
(1)順序排列時,只需比較(n-1)次,插入排序時間複雜度爲O(n);
(2)逆序排序時,需比較n(n-1)/2次,插入排序時間複雜度爲O(n^2);
(3)當原始序列雜亂無序時,平均時間複雜度爲O(n^2)。
插入排序過程當中,須要一個臨時變量temp存儲待排序元素,所以空間複雜度爲O(1)。
插入排序是一種穩定的排序算法。
大部分元素有序時較好
不能歸爲,好比最後一個數爲最小值,那麼全部的值都未在最終的位置。
1. 二分插入排序(折半插入排序 OR 拆半插入排序),採用折半查找方法。
直接插入排序算法在查找比較的過程當中採用的是順序查找;折半插入排序算法在查找比較的過程當中是採用折半查找的,所以折半插入排序的性能略高一些。
2. 希爾排序,也稱遞減增量排序算法,是插入排序的一種更高效的改進版本。但希爾排序是非穩定排序算法。
插入排序在對幾乎已經排好序的數據操做時,效率高,便可以達到線性排序的效率,但插入排序通常來講是低效的,由於插入排序每次只能將數據移動一位。
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; } }