經典排序演算法(2) 插入排序演算法 希爾排序詳解

2021-09-28 01:08:58 字數 1731 閱讀 2124

直接插入排序是一種最簡單的插入排序。

插入排序:每一趟將乙個待排序的記錄,按照其關鍵字的大小插入到有序佇列的合適位置裡,直到全部插入完成。

這個過程類似摸牌:

假設有一組無序序列 r0, r1, … , rn-1。

所以我們需要將 ri 和 r0 ~ ri-1 進行比較,確定要插入的合適位置。這就需要乙個內部迴圈,我們一般是從後往前比較,即從下標 i-1 開始向 0 進行掃瞄。

實現:

public class insertsort ;

//有序佇列[0,i-1] 待排序列[i,a.length-1]

for (int i=1;i=0&&a[j]>temp;j--)

a[j+1] = temp;

}for(int i=0;i當資料正序時,執行效率最好,每次插入都不用移動前面的元素,時間複雜度為 o(n)。

當資料反序時,執行效率最差,每次插入都要前面的元素後移,時間複雜度為 o(n2)。

所以,資料越接近正序,直接插入排序的演算法效能越好。

由直接插入排序演算法可知,我們在排序過程中,需要乙個臨時變數儲存要插入的值,所以空間複雜度為 1 。

直接插入排序的過程中,不需要改變相等數值元素的位置,所以它是穩定的演算法。

希爾(shell)排序又稱為縮小增量排序,它是一種插入排序。它是直接插入排序演算法的一種威力加強版。

希爾排序的基本思想是:

把記錄按步長 gap 分組,對每組記錄採用直接插入排序方法進行排序。

隨著步長逐漸減小,所分成的組包含的記錄越來越多,當步長的值減小到 1 時,整個資料合成為一組,構成一組有序記錄,則完成排序。

實現:public static void main(string args) ;

int gap = a.length/2;

//當步長的值減小到 1 時,迴圈終止

while(gap>=1)

a[j+gap] =temp;

}gap = gap / 2; // 減小增量

}for(int i=0;i步長的選擇是希爾排序的重要部分。只要最終步長為 1 任何步長序列都可以工作。

演算法最開始以一定的步長進行排序。然後會繼續以一定步長進行排序,最終演算法以步長為 1 進行排序。當步長為 1 時,演算法變為插入排序,這就保證了資料一定會被排序。

donald shell 最初建議步長選擇為 n/2 並且對步長取半直到步長達到 1。雖然這樣取可以比 o(n2)類的演算法(插入排序)更好,但這樣仍然有減少平均時間和最差時間的餘地。可能希爾排序最重要的地方在於當用較小步長排序後,以前用的較大步長仍然是有序的。

比如,如果乙個數列以步長 5 進行了排序然後再以步長 3 進行排序,那麼該數列不僅是以步長 3 有序,而且是以步長 5 有序。如果不是這樣,那麼演算法在迭代過程中會打亂以前的順序,那就不會以如此短的時間完成排序了。

已知的最好步長序列是由 sedgewick 提出的(1, 5, 19, 41, 109,…),該序列的項來自這兩個算式。

這項研究也表明「比較在希爾排序中是最主要的操作,而不是交換。」用這樣步長序列的希爾排序比插入排序和堆排序都要快,甚至在小陣列中比快速排序還快,但是在涉及大量資料時希爾排序還是比快速排序慢。

由上文的希爾排序演算法演示圖即可知,希爾排序中相等資料可能會交換位置,所以希爾排序是不穩定的演算法。

經典排序演算法2(插入排序)

a 插入排序分類 插入排序主要做兩件事,一是尋找插入點,二是移動插入點左側的資料 所以根據插入點的不同我們將插入排序又分為直接插入排序 折半插入排序和二路插入排序。原理 我將依次遍歷陣列中的元素,將陣列分為 使用中的 和 待使用中的 兩部分,在使用中的 資料時排序好的,待使用中的 資料時未排序的,我...

插入排序演算法 希爾排序

插入排序演算法 希爾排序 希爾排序思想是將陣列每次分成不同的陣列同時進行排序,劃分的方式是設定增量值,即h length 2,h 2 與直接排序最大的不同就是比較的陣列值下標間隔不同。希爾排序在資料量龐大的時候進行排序效率高,時間短。觀察下圖,根據以上思想,進行移動。如下 include void ...

排序演算法 插入排序 希爾排序

1 相鄰資料之間相比較。先是1,0 然後2,1 1,0 以此類推 總結 大for從1 n 小for從i 0,之後判斷交換即可 public void charusort for int i 1 i a.length i 2 希爾排序是插入排序特殊化,他不再比相鄰資料,而是可以比較類似1,4,13.的...