1. 程式人生 > 實用技巧 >直接插入排序

直接插入排序

  直接插入排序的基本思想:將一個記錄插入到已經排好序的有序表中,從而得到一個新的,記錄增長1的有序表。

  以順序表L = {0,5,3,4,6,2}為例,length = 6,參與排序的紀錄為r[1]~r[5],r[0]充當哨兵(中間變數),協助排序的進行。程式碼如下所示:

 1 //將一個記錄插入到已經排好序的有序表中
 2 //L->r[0]當作哨兵
 3 void InsertSort(SqList* L)
 4 {
 5     int i, j;
 6 
 7     //i從2開始,假設r[1]已經放好了位置
 8     //需要將每個記錄都插入到正確的位置,故i <= length
9 for (i = 2; i <= L->length; i++) 10 { 11 //將r[i]插入到已經排好序的有序表中 12 //若不滿足if條件,則說明不需要進行插入,不需要改變其位置 13 //若滿足if條件,則說明需要將r[i]插入到r[i-1]前面 14 if (L->r[i] < L->r[i - 1]) 15 { 16 L->r[0] = L->r[i]; //將需要插入有序表的記錄r[i]放到r[0]的位置 17 18 //
將已經排好序的有序表中大於r[i]的元素右移一位 19 //j=i-1;從第i個元素前面的一個元素開始從後往前根據條件執行右移 20 //一定會出現r[j] > r[0]不滿足的情況(當j=0時),從而跳出迴圈 21 //所以不需要判斷j是否小於0 22 for (j = i - 1; L->r[j] > L->r[0]; j--)//從後往前一個一個右移 23 L->r[j + 1] = L->r[j]; 24 25 L->r[j + 1
] = L->r[0];//將r[i]插入到空出來的位置,即正確的位置 26 } 27 } 28 }

  順序表中的記錄變化如下所示:

  (注意:圖中的 “=” 是相等的意思,是經過程式碼中賦值語句之後的結果,不是賦值的意思)

  當滿足if條件時,即r[i] < r[i-1],說明對於一個已經排好序的有序表,待插入的第i個記錄的關鍵字大於有序表中的最後一個記錄的關鍵字(有序表中關鍵字最大的記錄),需要將其插入有序表;否則,不需要做任何處理。在進行後續處理之前,將r[i]存入哨兵r[0]中,防止後續記錄後移的時候將r[i]的值覆蓋掉。

  將記錄插入有序表的過程中,由於並不知道需要將其插入到哪個位置,所以從有序表的最後一個記錄r[i-1]開始,依次與r[0](即r[i],r[i]到後面會被覆蓋)進行比較,若r[i-1]>r[0],說明需要將r[i]插入到r[i-1]的前面,故將r[i-1]進行後移,依次與有序表中的記錄(從後往前)進行比較,並進行後移處理,最終將帶插入記錄插入到正確的位置。

  “依次與有序表中的記錄(從後往前)進行比較”,如果從前往後進行記錄後移的話,後面的記錄將會被覆蓋掉。

  回顧 “直接插入排序的基本思想:將一個記錄插入到已經排好序的有序表中,從而得到一個新的,記錄增長1的有序表。”,如何理解這句話呢?在Step1中,{5}為已經排好序的有序表,我們將記錄3插入到{5}中,最終得到了一個新的,記錄增長1的有序表{3,5},依次進行,最終可以將一個順序表排成一個有序表。

參考書籍:程傑 著,《大話資料結構》,清華大學出版社。