插入排序演算法詳解(C++實現)
插入排序
輸入:n個數(a1,a2,...,an)。
輸出:輸入序列的一個排列(a1',a2',...,an'),使得a1'到an'為有序序列。
待排序的數稱為關鍵字key。
插入排序與平時生活中打牌時,整理手中牌的順序相似。最開始手中沒有牌,我們從桌上摸起一張牌,將它插入正確的位置,在插入時,我們需要依次進行比較;任何時候,我們手中的牌都是已經排好序的,並且這些牌都是桌上那副牌最頂上的一張。
插入排序偽程式碼表示:
Insertion-sort(A)
//引數A是待排序陣列
forj ← 2 to length[A]
dokey ← A[j]
▷ insert A[j] into the sorted sequence A[1…j-1]
//將A[j]插入已排好序的A[1…j-1]中
i← j-1
whileI > 0 and A[j] > key
doA[i+1] ← A[i]
I← i-1
A[i+1]← key
迴圈不變式與插入演算法的正確性:
在外層for迴圈(迴圈變數為j)的每一輪迭代開始,包含元素A[1…j-1]的子陣列構成已排好序的陣列。元素A[j+1…n]對應未排序的子陣列。實際上,已排好序的A[1…j-1]就是原陣列A[1…n]的前j-1個元素,只不過已經排好序了。
迴圈不變式的證明:
初始化:循第一輪開始時,j=2,此時子陣列只包含一個元素A[1],並且這個子陣列是已經排好序的,因此迴圈第一輪開始是正確的。
能否保持:在外層for迴圈中,要將A[j-1]、A[j-2]、A[j-3]等元素向右移動一個位置,直到找到A[j]的適當位置為止,此時將A[j]插入。(類似歸納法)因此如果迴圈的迭代開始之前它是正確的,那麼在下一次迭代開始之前,它也能保持正確。
終止:對於插入排序來說,當j大於n時,也就是j=n+1,外層for迴圈結束,外層for迴圈結束。在迴圈不變式中,將j替換為n+1,即有子陣列A[1…n]包含了原先的A[1…n]中的元素,但是現在已經排好了序。因此整個陣列就排好了序,演算法正確。
複雜度及穩定性:
最壞時間複雜度:O(n^2)
最優時間複雜度:O(n)
平均時間複雜度:O(n^2)
排序演算法穩定性:穩定
空間複雜度:O(1)
插入排序的C++語言實現:
void insertion_sort(int *A,int len)
{
for(int j=1; j<len; j++)
{
int key = A[j];
int i = j-1;
while (i>=0 && A[i]>key)
{
A[i+1] = A[i];
i--;
}
A[i+1] = key;
}
}