資料結構 23 排序篇之插入排序

2021-07-10 08:57:38 字數 3844 閱讀 6130

一趟直接插入排序的基本思想: 將記錄l.r[i]插入到有序子串行l.r[1..i-1]中,使記錄的有序序列從l.r[1..i-1]變為l.r[1..i]。 完成這個「插入」分三步進行:

1.查詢l.r[i]在有序子串行l.r [1..i-1]中的插入位置j;

2.將l.r [j..i-1]中的記錄後移乙個位置;

3.將l.r [i]複製到l.r [j]的位置上。

整個排序過程進行n–1趟插入,即:先將序列中的第1個記錄著成乙個有序的子串行,然後從第2個記錄起逐個插入,直至整個序列變成接關鍵字非遞減有序序列為止。

l[j+1] = l[j];//利用監視哨

//當l[0] >=

//當是因為=而跳出迴圈時(j後來沒有自減),l[0]插在l[j]的後面以保證了「穩定」

l[j+1] = l[0];

} }public static void main(string args) ; //0號單元未使用

insertsort(test);

for(int i = 1; i <= test.length-1; i++)

system.out.print(test[i]+" ");

}}執行結果:

直接插入排序效能分析 ,實現排序的基本操作有: (1)「比較」 關鍵字的大小 (2)「移動」記錄

對於直接插入排序: 

最好情況「比較」次數:n-1;「移動」次數:2(n-1)

最壞的情況「比較」和「移動」的次數均達到最大值,分別為:(n+2)(n-1)/2;(n+4)(n-1)/2

由於待排記錄序列是隨機的,取上述二值的平均值。所以直接插入排序的時間複雜度為o(n^2)

直接插入排序是「穩定的」:關鍵碼相同的兩個記錄,在整個排序過程中,不會通過比較而相互交換。

考慮到 l.r[1..i-1] 是按關鍵字有序的有序序列,則可以利用折半查詢實現「 l.r[1…i-1]中查詢 l.r[i] 的插入位置」如此實現的插入排序為折半插入排序。折半插入排序在尋找插入位置時,不是逐個比較而是利用折半查詢的原理尋找插入位置。待排序元素越多,改進效果越明顯。

//此時high = low-1,且high+1即low的位置即為要插入的位置

for(int j = i-1; j >= low; j--)

l[j+1] = l[j];

l[low] = l[0];

} }public static void main(string args) ; //0號單元未使用

binaryinsertsort(test);

for(int i = 1; i <= test.length-1; i++)

system.out.print(test[i]+" ");

}}執行結果:

折半插入排序減少了關鍵字的比較次數,但記錄的移動次數不變,其時間複雜度與直接插入排序相同,時間複雜度為o(n^2)。折半插入排序是「穩定的」。

希爾排序(shell sort)又稱為「縮小增量排序」。其基本思想是:先將整個待排元素序列分割成若干個子串行(由相隔某個「增量」的元素組成的)分別進行直接插入排序,待整個序列中的元素基本有序(增量足夠小)時,再對全體元素進行一次直接插入排序。因為直接插入排序在元素基本有序的情況下(接近最好情況),效率是很高的,因此希爾排序在時間效率上比前兩種方法有較大提高。

*///對順序表l做一趟希爾排序,本演算法和一趟直接插入排序相比,做了如下修改:

//1.前後記錄位置的增量式dk,而不是1

只是暫存單元,而不再是哨兵

public static void shellinsert(int l, int dk){

/*對於下面for迴圈的i = i+dk和i++的分析:

一趟希爾排序裡有l.length/dk個子序列,每個子串行要進行直接插入排序,即要進行l.length/dk個直接插入排序

子串行輪著來(有點併發的感覺),即第乙個子串行的第2個數排完序,然後是第2個子序列的第2個數排序,然後是第3個子序列。。。

i繼續自增,然後是第1個子序列的第3個數往第乙個子串行的1->2的有序子串行裡插入並排序,然後是第2個子序列的第3個數

往第2個子序列的1->2的有序子串行裡插入並排序,然後是第3個子序列的第3個數往第3個子序列的1->2的有序子串行裡插入並排序。。。

i繼續自增,然後是第1個子序列的第4個數往第乙個子串行的1->3的有序子串行裡插入並排序,接著

第2個子序列的第4個數往第2個子序列的1->3的有序子串行裡插入並排序.。。。。。以此類推,直到所有的完成

*///相當於每個子串行的第乙個數都被看成是每個子串行的有序子串行

for(int i = 1+dk; i <= l.length-1; i++){

l[0] = l[i];

//找l[i]應該插入的位置

int j = i-dk;

for(; j>0&&l[0]執行結果:

雖然我們給出的演算法是三層迴圈,最外層迴圈為log2n數量級,中間的for迴圈是n數量級的,內迴圈遠遠低於n數量級,因為當分組較多時,組內元素較少;此迴圈次數少;當分組較少時,組內元素增多,但已接近有序,迴圈次數並不增加。因此,希爾排序的時間複雜性在o(nlog2n)和o(n^2 )之間,大致為o(n^1. 3)

希爾排序的時間複雜度較直接插入排序低。希爾排序的分析是乙個複雜的問題,因為它的時間是和所取「增量」序列的函式密切相關。到目前為止,還沒有求得一種最好的增量序列,但有大量的區域性結論。 

注意:應使增量序列中的值沒有除1之外的公因子,並且最後乙個增量值必須等於1。

由於希爾排序對每個子串行單獨比較,在比較時進行元素移動,有可能改變相同排序碼元素的原始順序,因此希爾排序是不穩定的。

資料結構二 排序(插入排序和希爾排序)

插入排序在哪些情況下效率高?1.插入的序列基本有序 2.序列較小的情況下 include include include include define max 10 獲取時間,毫秒 long gettime 列印 void printarr int arr,int len 插入排序 void ins...

02 排序 插入排序

基本原理 直接插入法思想 1.在原始資料中,將第乙個資料作為已排序的資料序列 2.從陣列中獲取下乙個元素,在已經排序好的元素中從後向前掃瞄,並判斷該元素與已排列好的的大小 3.若排序序列的元素大於新元素,則將該元素移到下一位置 4.重複步驟三,直到找到已排序的元素小於或者等於行元素的位置 5.將新元...

資料結構 排序之插入排序

插入排序o n2 的執行時間 思想是 若陣列長度為n 那麼把陣列序號從1到n 1的值依次往前進行比較 這裡需要乙個for迴圈 注意每個數在比較的時候它前面的資料都是已經排好序號的 因為從序號為1時就開始排序了 注意我們這裡用類似堆中下浮和上浮的交換方法 把需要交換的資料拿出來 和前面的資料依次進行比...