插入排序的適用範圍:對於少量元素的排序,他是一個有效演算法。
由於書中的虛擬碼太經典,所以忍不住抄一下:
//虛擬碼INSERTION-SORT(A)for j= 2 to A.lengthkey=A[j]//insert A[j] into A[1...(j-1)]i=j-1;while i>0 and A[i]>keyA[i+1]=A[i] i=i-1A[i+1]=key
c++實現:
/* 輸入:A[1...(n-1)] *原址排序 *version1 */template<typename T>void insertion_sort(T* A,int n){int key=0;//key初始化for(int j=1;j<n;++j){//進行A[j]的插入工作key=A[j];int i=j-1;while(i>=0 && A[i]>key){A[i+1]=A[i];i=i-1;}A[i+1]=key;}}
再說點理論性的東西,這才是最重要的:
這一章中,作者引出了一個重要的演算法分析工具,迴圈不變式(就是每次for或while迴圈都不變的特性),這對於演算法正確性的證明,非常重要。
如果讓我證明這個演算法正確性的話,我肯定就是弄一個較短的序列來測試一下,發現每次迴圈之前,A[1.。。j-1](由於偽碼數組是從1開始,c++是從0開始,此處分析以偽碼為標準)都是已序的-----書中的迴圈不變式的表示:
for迴圈的每次迭代開始時,子數組A[1..j-1]由原來在A[1..j-1]中的元素組成,但已排序
迴圈不變式的證明主要分三段:初始化,保持,終止。(此處略去證明)
演算法用迴圈不變式證明是正確的之後,現在來分析一下複雜度,容易得出複雜度為θ(n^2)。
感悟:給定一組數,進行排序。腦海中蹦出的想法是,選擇一個最小的元素,放在第一位;然後選擇次小的,放在第二位。。。這種暴力方法效率不及插入排序。那麼,插入排序的魅力在什麼地方呢?程式的設計方法。插入排序採用的程式設計方法是---增量法:在排序子數組A[1..j-1]後,將單個元素A[j]插入子數組的適當位置,產生排序好的數組,這是一種有效並且非常有價值的思想,例如後面好多動態規劃的設計就是使用增量法的思路。