排序小結 2 插入排序

2021-05-22 09:58:20 字數 4160 閱讀 5611

插入排序

插入排序(insertion sort)的基本思想是:每次將乙個待排序的記錄,按其關鍵字大小插入到前面已經排好序的子檔案中的適當位置,直到全部記錄插入完成為止。

本節介紹兩種插入排序方法:直接插入排序和希爾排序。

直接插入排序基本思想

1、基本思想

假設待排序的記錄存放在陣列r[1..n]中。初始時,r[1]自成1個有序區,無序區為r[2..n]。從i=2起直至i=n為止,依次將r[i]插入當前的有序區r[1..i-1]中,生成含n個記錄的有序區。

2、第i-1趟直接插入排序:

通常將乙個記錄r[i](i=2,3,…,n-1)插入到當前的有序區,使得插入後仍保證該區間裡的記錄是按關鍵字有序的操作稱第i-1趟直接插入排序。

排序過程的某一中間時刻,r被劃分成兩個子區間r[1..i-1](已排好序的有序區)和r[i..n](當前未排序的部分,可稱無序區)。

直接插入排序的基本操作是將當前無序區的第1個記錄r[i]插人到有序區r[1..i-1]中適當的位置上,使r[1..i]變為新的有序區。因為這種方法每次使有序區增加1個記錄,通常稱增量法。

插入排序與打撲克時整理手上的牌非常類似。摸來的第1張牌無須整理,此後每次從桌上的牌(無序區)中摸最上面的1張並插入左手的牌(有序區)中正確的位置上。為了找到這個正確的位置,須自左向右(或自右向左)將摸來的牌與左手中已有的牌逐一比較。

一趟直接插入排序方法

1.簡單方法

首先在當前有序區r[1..i-1]中查詢r[i]的正確插入位置k(1≤k≤i-1);然後將r[k..i-1]中的記錄均後移乙個位置,騰出k位置上的空間插入r[i]。

注意:若r[i]的關鍵字大於等於r[1..i-1]中所有記錄的關鍵字,則r[i]就是插入原位置。

2.改進的方法

一種查詢比較操作和記錄移動操作交替地進行的方法。

具體做法:

將待插入記錄r[i]的關鍵字從右向左依次與有序區中記錄r[j](j=i-1,i-2,…,1)的關鍵字進行比較:

① 若r[j]的關鍵字大於r[i]的關鍵字,則將r[j]後移乙個位置;

②若r[j]的關鍵字小於或等於r[i]的關鍵字,則查詢過程結束,j+1即為r[i]的插入位置。

關鍵字比r[i]的關鍵字大的記錄均已後移,所以j+1的位置已經騰空,只要將r[i]直接插入此位置即可完成一趟直接插入排序。

直接插入排序演算法

1.演算法描述

2.哨兵的作用

演算法中引進的附加記錄r[0]稱監視哨或哨兵(sentinel)。

哨兵有兩個作用:

① 進人查詢(插入位置)迴圈之前,它儲存了r[i]的副本,使不致於因記錄後移而丟失r[i]的內容;

② 它的主要作用是:在查詢迴圈中"監視"下標變數j是否越界。一旦越界(即j=0),因為r[0].key和自己比較,迴圈判定條件不成立使得查詢迴圈結束,從而避免了在該迴圈內的每一次均要檢測j是否越界(即省略了迴圈判定條件"j>=1")。

注意:① 實際上,一切為簡化邊界條件而引入的附加結點(元素)均可稱為哨兵。

【例】單鏈表中的頭結點實際上是乙個哨兵

② 引入哨兵後使得測試查詢迴圈條件的時間大約減少了一半,所以對於記錄數較大的檔案節約的時間就相當可觀。對於類似於排序這樣使用頻率非常高的演算法,要盡可能地減少其執行時間。所以不能把上述演算法中的哨兵視為雕蟲小技,而應該深刻理解並掌握這種技巧。

給定輸入例項的排序過程

設待排序的檔案有8個記錄,其關鍵字分別為:49,38,65,97,76,13,27,49。為了區別兩個相同的關鍵字49,後乙個49的下方加了一下劃線以示區別。其排序過程見【動畫模擬演示】

演算法分析

1.演算法的時間效能分析

對於具有n個記錄的檔案,要進行n-1趟排序。

各種狀態下的時間複雜度:

┌─────────┬─────┬──────┬──────┐

│ 初始檔案狀態     │   正序   │     反序   │無序(平均)  │

├─────────┼─────┼──────┼──────┤

│ 第i趟的關鍵      │   1      │     i+1    │ (i-2)/2  │

│ 字比較次數       │          │            │            │

├─────────┼─────┼──────┼──────┤

│總關鍵字比較次數  │   n-1    │(n+2)(n-1)/2│ ≈n2/4     │

├─────────┼─────┼──────┼──────┤

│第i趟記錄移動次數 │   0      │ i+2        │ (i-2)/2  │

├─────────┼─────┼──────┼──────┤

│總的記錄移動次數  │   0      │(n-1)(n+4)/2│ ≈n2/4     │

├─────────┼─────┼──────┼──────┤

│時間複雜度        │  0(n)  │ o(n2)    │ o(n2)    │

└─────────┴─────┴──────┴──────┘

注意:初始檔案按關鍵字遞增有序,簡稱"正序"。

初始檔案按關鍵字遞減有序,簡稱"反序"。

2.演算法的空間複雜度分析

演算法所需的輔助空間是乙個監視哨,輔助空間複雜度s(n)=o(1)。是乙個就地排序。

3.直接插入排序的穩定性

直接插入排序是穩定的排序方法。

希爾排序(shell sort)是插入排序的一種。因d.l.shell於2023年提出而得名。

希爾排序基本思想

基本思想:

先取乙個小於n的整數d1作為第乙個增量,把檔案的全部記錄分成d1個組。所有距離為dl的倍數的記錄放在同乙個組中。先在各組內進行直接插人排序;然後,取第二個增量d2

1重複上述的分組和排序,直至所取的增量dt=1(dt

t-l<…2

1),即所有記錄放在同一組中進行直接插入排序為止。

該方法實質上是一種分組插入方法。

給定例項的shell排序的排序過程

假設待排序檔案有10個記錄,其關鍵字分別是:

49,38,65,97,76,13,27,49,55,04。

增量序列的取值依次為:

5,3,1

排序過程如【動畫模擬演示】。

shell排序的演算法實現

1. 不設監視哨的演算法描述

注意:當增量d=1時,shellpass和insertsort基本一致,只是由於沒有哨兵而在內迴圈中增加了乙個迴圈判定條件"j>0",以防下標越界。

2.設監視哨的shell排序演算法

具體演算法【參考書目[12] 】

演算法分析

1.增量序列的選擇

shell排序的執行時間依賴於增量序列。

好的增量序列的共同特徵:

① 最後乙個增量必須為1;

② 應該盡量避免序列中的值(尤其是相鄰的值)互為倍數的情況。

有人通過大量的實驗,給出了目前較好的結果:當n較大時,比較和移動的次數約在nl.25到1.6n1.25之間。

2.shell排序的時間效能優於直接插入排序

希爾排序的時間效能優於直接插入排序的原因:

①當檔案初態基本有序時直接插入排序所需的比較和移動次數均較少。

②當n值較小時,n和n2的差別也較小,即直接插入排序的最好時間複雜度o(n)和最壞時間複雜度0(n2)差別不大。

③在希爾排序開始時增量較大,分組較多,每組的記錄數目少,故各組內直接插入較快,後來增量di逐漸縮小,分組數逐漸減少,而各組的記錄數目逐漸增多,但由於已經按di-1作為距離排過序,使檔案較接近於有序狀態,所以新的一趟排序過程也較快。

因此,希爾排序在效率上較直接插人排序有較大的改進。

3.穩定性

希爾排序是不穩定的。參見上述例項,該例中兩個相同關鍵字49在排序前後的相對次序發生了變化。

排序 2 插入排序

插入排序 1.想象桌子上有一堆撲克牌,左手中只有一張,數值是2,然後從桌子上拿起一張,數值是5,將這張撲克牌的和左手上的撲克牌進行比較,把較小的哪乙個放到左邊,於是左手上的撲克牌變成兩張,排列從左到右分別是 2,5。2.然後再從桌子上拿起一張牌3,此時左手上已經有兩張牌並且已經排好順序,左邊的小右邊...

排序演算法 2 插入排序

插入排序 insertion sort 的基本思想是 每次將乙個待排序的記錄,按其關鍵字大小插入到前面已經排好序的子檔案中的適當位置,直到全部記錄插入完成為止。本節介紹兩種插入排序方法 直接插入排序和希爾排序。直接插入排序 直接插入排序基本思想 1 基本思想 假設待排序的記錄存放在陣列r 1.n 中...

排序演算法 2 插入排序

思路是 每次從未排好的序列中選出第乙個元素插入到已排好的序列中。步驟可以大致歸納如下 1.從未排好的序列中拿出首元素,並把它賦值給temp變數 2.從排好的序列中,依次與temp進行比較,如果元素比temp大,則將元素後移 實際上放置temp的元素位置已經空出 3.直到找到乙個元素比temp小,將t...