1. 簡述
假設待排序數組為 int array[], 數組長度為n。
第1趟,認為array[0]-array[0]已經排序,把array[1]插入到合適的位置。
第2趟,認為array[0]-array[1]已經排序,把array[2]插入到合適的位置。
···
第n-1趟,認為array[0]-array[n-2]已經排序,把array[n-1]插入到合適的位置。
2. 複雜度
最好的時間複雜度是O(n),對已經排序好的數組,只需要n-1次比較就可以了。平均時間複雜度和最壞時間複雜度都是O(n^2)。
在每次趟中,尋找合適位置時,可以使用二分尋找的方法,來減少比較次數。
穩定性上,如果不使用二分尋找,那麼是穩定的排序,否則是不穩定的排序。
3. 代碼
void insertion_sort(int array[], int n) {
int pos, left, right, mid, tmp;
for(int i=1; i<n; i++) {
if(array[i] >= array[i-1]) { // 不需要插入
continue;
}
else if(array[i] < array[0]) { // 插入到最前面
pos = 0;
}
else { // 使用二分尋找,來確定插入位置
left = 0; right = i-1;
while(right - left > 1) {
mid = (left+right)/2;
if(array[i] < mid) right = mid;
else left = mid;
}
pos = right;
}
// 插入過程
tmp = array[i];
for(int j=i; j>pos; j--)
array[i] = array[i-1];
array[pos] = tmp;
}
}
實際上,插入排序的元素賦值操作往往是比較耗時的,二分的方法只能減少一些比較的次數,並不能減少元素移動的次數,因此對於效能提升不是很多。下面給出一個比較“簡化”的插入排序代碼:
void insertion_sort(int array[], int n) {
int temp,i,j;
for(i=1; i<n; i++) {
temp = array[i];
for(j=i; j>0 && temp<array[j-1]; j--) { // 此時array[j]==temp
array[j] = array[j-1];
}
array[j] = temp;
}
}
上面代碼舉個例子來說明一下,比如對1 3 4 5 6 7 2,現在要把最後的2插入到前面有序的數組中了,首先,temp=2,然後就用temp與前面的這些數字逐個比較,如果temp更小,那麼就把前面的數字後移一位,直到結束,在把temp放到空出的位置。對於例子就是在迴圈結束時,1 3 3 4 5 6 7 ,temp=2, j=1,然後array[1]=2,得到1 2 3 4 5 6 7
4. 參考資料
維基百科-插入排序 http://en.wikipedia.org/wiki/Insertion_sort