淺談直接插入排序演算法思想以及時間複雜度分析
研究意義
直接插入排序是最基本的一種排序演算法,其思想簡單,容易掌握,對後期的學習也有一定的幫助。
必備知識(之後不再敘述)
排序:將一組雜亂無章的資料排列成一個按關鍵字有序的序列。
穩定性:關鍵值相同的記錄,排序前後的相對次序不變。
排序前: 15 1 4 3 4
排序後: 1 3 4 4 15 穩定排序
1 3 4 4 15 不穩定排序
內排序與外排序:內排序是指記錄集全部在記憶體中 ;外排序是指記錄集部分在記憶體中,排序過程中,需訪問外存 。
時間複雜度: 排序的時間複雜度可用演算法執行中的資料比較次數與資料移動次數
空間複雜度:排序過程中需要使用的輔助儲存空間。
等差數列 前n項和公式:Sn=na1+n(n-1)d/2或Sn=n(a1+an)/2
主要內容:
一、演算法思路(直接插入到已經有序的序列中)
設已存在一個有序子序列;每趟將一個記錄按關鍵值大小插入到有序子序列中。初始化時,有序子序列只有一個記錄。
直接插入排序就可以看作在一個只有一個元素的陣列中插入資料,每一次插入都插入到合適位置。插入時前面的序列已經有序,讓我們來模擬一下直接插入排序的方法。
假設我們拿到的資料是 5,7,3,8,2而手工排序的思路是 5 然後比較7和5的大小 ,合併為5,,7, 再在已經有序的5,7序列中插入3變為3,5,7,以此類推。
完整的排序思路 5,7,3,8,2 (初始狀態)
5,7,3,8,2
3,5,7,8,2
3,5,7,8,2
2,3,5,7,8 (排序結束)
紅色標記的數字為每一次需要排序的數字(需要插入的數字).
二、實現程式碼
#include <stdio.h> #include <stdlib.h> //直接插入排序 int main() { int a[10]={0,5,7,3,8,2,4,15,18,21}; int i=0,j=0,k=0; printf("排序前的資料為:"); for(k=1;k<10;k++) { printf("%3d",a[k]); } printf("\n"); for(i=2;i<10;i++) { a[0]=a[i]; //a[0]為監視哨兵 for(j=i-1;a[0]<a[j];j--) { a[j+1]=a[j]; //資料移動移動 } a[j+1]=a[0];//插入到正確位置 } printf("排序後的資料為:"); for(k=1;k<10;k++) { printf("%3d",a[k]); } return 0; }
注意:監視哨的作用:儲存副本,避免陣列下標越界。
三、演算法分析
一個記錄的輔助儲存空間 -----監視哨
當問題規模為n時
最好情況(原本就是有序的)
比較次數:Cmin=n-1
移動次數:Mmin=0
最差情況(逆序)
比較次數:Cmax=2+3+4+……+n=(n+2)n/2
移動次數:Mmax=1+2+3+……+n-1=n*n/2
若待排序物件序列中出現各種可能排列的概率相同,則可取上述最好情況和最壞情況的平均情況。在平均情況下的關鍵字比較次數和物件移動次數約為 n^2/4。因此,直接插入排序的時間複雜度為 o(n^2)。
另外直接插入排序是一種穩定的排序方法。