插入排序是一種簡單直觀的排序算法,它也是基於比較的排序算法。它的工做原理是經過不斷擴張有序序列的範圍,對於未排序的數據,在已排序中從後向前掃描,找到相應的位置並插入。插入排序在實現上一般採用就地排序,於是空間複雜度爲O(1)。在從後向前掃描的過程當中,須要反覆把已排序元素逐步向後移動,爲新元素提供插入空間,所以插入排序的時間複雜度爲O(n^2);html
通常來講,插入排序都採用在數組上就地排序實現。具體算法描述以下:算法
假設咱們要對數組{12,4,5,2,6,14}進行插入排序,排序過程爲:
數組
template <typename T> void InsertSort(T array[],int length) { if (array == nullptr || length < 0) return; int i, j; for (i = 1; i < length; i++) { if (array[i]<array[i - 1]) { int temp = array[i]; for (j = i - 1; array[j]>temp; j--) //元素後移 { array[j + 1] = array[j]; } array[j+1] = temp; //在合適的位置上出入元素 } } }
插入排序不適合對大量數據進行排序應用,但排序數量級小於千時插入排序的效率還不錯,能夠考慮使用。插入排序在STL的sort算法和stdlib的qsort算法中,都將插入排序做爲快速排序的補充,用於少許元素的排序(一般爲8個或如下)。數據結構
直接插入排序採用就地排序,空間複雜度爲O(1).函數
直接插入排序是穩定的,不會改變相同元素的相對順序。優化
上面的插入排序實現中,爲了找到元素的合適的插入位置,咱們採用從後到前遍歷的順序查找進行比較,爲了減小比較的次數,咱們能夠換種查找策略:採用二分查找。
咱們定義一個二分查找函數,函數返回插入位置的下標:編碼
/*二分查找函數,返回插入下標*/ template <typename T> int BinarySearch(T array[], int start, int end, T k) { while (start <= end) { int middle = (start + end) / 2; int middleData = array[middle]; if (middleData > k) { end = middle - 1; } else start = middle + 1; } return start; } //二叉查找插入排序 template <typename T> void InsertSort(T array[], int length) { if (array == nullptr || length < 0) return; int i, j; for (i = 1; i < length; i++) { if (array[i]<array[i - 1]) { int temp = array[i]; int insertIndex = BinarySearch(array, 0,i, array[i]);//使用二分查找在有序序列中進行查找,獲取插入下標 for (j = i - 1; j>=insertIndex; j--) //移動元素 { array[j + 1] = array[j]; } array[insertIndex] = temp; //插入元素 } } }
咱們這個二分查找的算法並不會由於等於某一個值而中止查找,它將查找整個序列直到start<=end條件不知足而獲得插入的位置,因此對於長度爲n的數組來講,比較次數爲log2n ,時間複雜度爲O(log2n)。二分插入排序的主要操做爲比較+後移賦值,則:code
空間複雜度上, 二分插入排序也是就地排序算法,它的空間複雜度爲O(1).htm
二分插入排序是穩定的。元素的相對順序在排序後不會被改變。blog
原創文章,轉載請註明: http://www.cnblogs.com/QG-whz/p/5194569.html