插入排序演算法+優化 (二分查詢優化有序部分)C語言實現
阿新 • • 發佈:2019-01-06
直接插入排序
插入排序思想
直接插入排序思想是將待排序的陣列看作兩個部分:有序部分和無序部分,排序過程就是不斷將無序部分的元素插入到有序部分合適的位置上,使有序部分元素不斷增加而無序部分資料不斷減少,直到陣列全部有序為止。
假設陣列A[0...n-1]
(1)初始時,A[0]作為有序部分,A[1...n-1]為無序部分;
(2)在有序部分進行比較和移動,為無序部分的第一個元素A[1]找到合適的位置,並插入到有序部分,使A[0,1]構成新的有序部分,而A[2...n-1]為剩下的無序部分;
插入排序的效能
時間複雜度:直接插入排序的最好情況是待排序列已經是升序排列了,在這種情況下,每次只需要進行一次比較操作(一共需要n-1次),不需要移動元素操作,此時時間複雜度為O(n)。而最壞情況是待排序列是降序排列的,此時每次需要進行i次比較和i次移動,i從1到n-1,所以一共需要n(n-1)/2次,此時時間複雜度為O(n^2)。平均來說插入排序演算法複雜度為O(n^2)。
空間複雜度:僅需要一個輔助變數,所以為O(1);
穩定性:穩定的就地排序(穩定性還需要程式碼設計來保證);
使用場合:插入排序不適合對於資料量比較大的排序應用。但是,如果需要排序的資料量很小,例如,量級小於千,那麼插入排序還是一個不錯的選擇,而且,如果待排資料已經是基本有序的,那麼插入排序將是一個絕佳的選擇(為什麼?見時間複雜度分析)。 插入排序在工業級庫中也有著廣泛的應用, 在STL的sort演算法和stdlib的qsort演算法中,都將插入排序作為快速排序的補充,用於少量元素的排序(通常為8個或以下)。
插入排序思想
直接插入排序思想是將待排序的陣列看作兩個部分:有序部分和無序部分,排序過程就是不斷將無序部分的元素插入到有序部分合適的位置上,使有序部分元素不斷增加而無序部分資料不斷減少,直到陣列全部有序為止。
假設陣列A[0...n-1]
(1)初始時,A[0]作為有序部分,A[1...n-1]為無序部分;
(2)在有序部分進行比較和移動,為無序部分的第一個元素A[1]找到合適的位置,並插入到有序部分,使A[0,1]構成新的有序部分,而A[2...n-1]為剩下的無序部分;
(3)按照步驟(2)執行,直到陣列有序。
插入排序的優化
由插入排序的特點可知,在陣列有序部分進行比較和查詢待排元素的合適位置時,除了簡單的由右向左的順序遍歷外,在通常情況下可以採用效率更高的二分查詢方法找到該位置,此時查詢的時間複雜度降低。但是需要注意的是:雖然比較和查詢時間複雜度降低,但是每次需要移動的元素個數與順序比較和查詢是相同的。實現程式碼(C語言實現)如下。
void binarySearch(int *a,int len) { int i,value,j; int low=0,high=0; int mid; for(i=1;i<len;i++) { value=a[i]; low=0; high=i-1; while(low<=high) { mid=(low+high)>>1; if(a[mid]<value) { low=mid+1; } else { high=mid -1; } } for(j=i-1;j>=low;j--) { a[j+1]=a[j]; } a[low]=value; } for(i=0;i<len;i++) { printf("%d ",a[i]); } } int main() { int a[]={98,52,12,456,953,65447,852,462,1532}; binarySearch(a,9); return 0 ; }
插入排序的效能
時間複雜度:直接插入排序的最好情況是待排序列已經是升序排列了,在這種情況下,每次只需要進行一次比較操作(一共需要n-1次),不需要移動元素操作,此時時間複雜度為O(n)。而最壞情況是待排序列是降序排列的,此時每次需要進行i次比較和i次移動,i從1到n-1,所以一共需要n(n-1)/2次,此時時間複雜度為O(n^2)。平均來說插入排序演算法複雜度為O(n^2)。
空間複雜度:僅需要一個輔助變數,所以為O(1);
穩定性:穩定的就地排序(穩定性還需要程式碼設計來保證);
使用場合:插入排序不適合對於資料量比較大的排序應用。但是,如果需要排序的資料量很小,例如,量級小於千,那麼插入排序還是一個不錯的選擇,而且,如果待排資料已經是基本有序的,那麼插入排序將是一個絕佳的選擇(為什麼?見時間複雜度分析)。 插入排序在工業級庫中也有著廣泛的應用,