1 / 20

11.3 插入排序

11.3 插入排序. 插入排序( insertion sorting )是以前使用卡片儲存資料時代最常使用的排序方法,使用者挑出一張卡片,決定它的位置,就插入適當的位置,同樣的方式也適用於程式,在插入排序處理的一個回合裡,會插入一個記錄進入已排序完成的串列裡頭。 本小節將介紹兩種插入排序方法:直接插入以及謝耳( shell )排序法。. 11.3.1 直接插入排序.

Download Presentation

11.3 插入排序

An Image/Link below is provided (as is) to download presentation Download Policy: Content on the Website is provided to you AS IS for your information and personal use and may not be sold / licensed / shared on other websites without getting consent from its author. Content is provided to you AS IS for your information and personal use only. Download presentation by click this link. While downloading, if for some reason you are not able to download a presentation, the publisher may have deleted the file from their server. During download, if you can't get a presentation, the file might be deleted by the publisher.

E N D

Presentation Transcript


  1. 11.3 插入排序 • 插入排序(insertion sorting)是以前使用卡片儲存資料時代最常使用的排序方法,使用者挑出一張卡片,決定它的位置,就插入適當的位置,同樣的方式也適用於程式,在插入排序處理的一個回合裡,會插入一個記錄進入已排序完成的串列裡頭。 • 本小節將介紹兩種插入排序方法:直接插入以及謝耳(shell)排序法。

  2. 11.3.1 直接插入排序 • 在直接插入排序法(direct insertion sort)裡,資料串列分成兩個部份:已排序及未排序次串列。在每一個排序回合裡,未排序次串列裡第一項資料移動至已排序次串列裡的適當位置。若有 n 項資料,最多需要 n-1 次的排序回合。

  3. 直接插入排序舉例

  4. 直接插入排序函式 • 直接插入排序函式原型宣告如下: • void insertSort(int k[], int L, int R) • 需要三個引數,陣列 k[],左範圍註標 L,右範圍註標 R。 • 先將標的元素存入 kk,其後的元素逐一與 kk 比較,若較 kk 大則搬移至右一位,空出本身位置,直到較 kk 小時,就找到 kk 的位置,置入 kk 值。

  5. 編譯執行 • ch11> gcc insertsort.c -o insertsort.exe <Enter> • ch11> insertsort.exe <Enter> • 7 22 31 44 55 77

  6. 11.3.2 謝耳排序 • 謝耳排序法(Shell sort)是記念創造者 Donald L. Shell 先生,是一款直接插入排序法的改良版本,也是屬於快速排序法。 • 謝耳排序法將 N 個資料分割成 M 個分段(segment),每一個分段包含 N/M 個資料,若不能整除則每一段資料個數會有不同。 • 若 N=8,M=3 則分段如下: • k[0] k[1] k[2] k[3] k[4] k[5] k[6] k[7] • 第一段包含 k[0]、k[3]、k[6],第二段包含 k[1]、k[4]、k[7],第三段包含 k[2]、k[5]。

  7. 謝耳排序分M段 • 若 N=8,M=2 則分段如下: • k[0] k[1] k[2] k[3] k[4] k[5] k[6] k[7] • 第一段包含 k[0]、k[2]、k[4]、k[6],第二段包含 k[1]、k[3]、k[5],k[7]。 • 若 N=8,M=1 則分段如下: • k[0] k[1] k[2] k[3] k[4] k[5] k[6] k[7] • 第一段包含 k[0]、k[1]、k[2]、k[3]、k[4]、k[5]、k[6]、k[7],且是惟一的一段。

  8. 謝耳排序舉例

  9. 謝耳排序 • 謝耳排序函式原型宣告如下: • void shellSort(int k[], int L, int R) • 需要三個引數,陣列 k[],左範圍註標 L,右範圍註標 R。 • 首先設 m=(R-L+1)/2=(7-0+1)/2=4,分成四段,第一段 k[0]、k[4] ,第二段 k[1]、k[5],第三段 k[2]、k[6],第四段 k[3]、k[7],各段分別以插入排序法排序,稱為第一回合。 • 然後設定 m=m/2=2,分為兩段,第一段 k[0]、k[2]、k[4]、k[6],第二段 k[1]、k[3],k[5]、k[7],各段分別以插入排序法排序,稱為第二回合。 • 然後設定 m=m/2=1,分為一段 k[0]、k[1]、k[2]、k[3]、k41]、k[5],k[6]、k[7],以插入排序法排序,稱為第三回合,完成排序。

  10. 編譯執行 • ch11> gcc shellsort.c -o shellsort.exe <Enter> • ch11> shellsort.exe <Enter> • Original array : • 76 61 13 8 29 20 79 24 • m=4 • 29 20 13 8 76 61 79 24 • m=2 • 13 8 29 20 76 24 79 61 • m=1 • 8 13 20 24 29 61 76 79 • After shell sort : • 8 13 20 24 29 61 76 79

  11. 11.4 互換排序 • 排序的第三類別屬於互換排序(exchange),本小節說明氣泡排序法(bubble sort)以及快速排序法(quick sort)。

  12. 11.4.1 氣泡排序 • 氣泡排序在任何時刻,資料串列都被分成兩個次串列:未排序以及已排序次串列。我們從未排序次串列裡頭鄰近兩個資料比較,不合指定順序者互換其值,從右往左逐一比較互換。 • 如此選擇互換後,屬於已排序次串列逐漸擴展,而屬於未排序次串列之範圍逐漸縮小,比較互換的動作一直重複,一直到沒有未排序次串列為止。

  13. 氣泡排序法舉例

  14. 上圖是六個資料項 k[] 陣列的氣泡排序法,逐一從右往左比較互換。 • 1. k[5] 與 k[4] 比較,52 比 73 小, • 互換,k[5]=73,k[4]=52。 • 2. k[4] 與 k[3] 比較,52 較 15 大, • 已合乎右大左小的順序,因此不互換。 • 3. k[3] 與 k[2] 比較,15 較 41 小, • 互換,k[3]=41,k[2]=15。 • 4. k[2] 與 k[1] 比較,15 較 78 小, • 互換,k[2]=78,k[1]=15。 • 5. k[1] 與 k[0] 比較,15 較 12 大,不互換。 • 這五個動作稱為第一回合,原資料變更如下: • [0] [1] [2] [3] [4] [5] • ----- ----- ----- ----- ----- ----- • 12 15 78 41 52 73

  15. 編譯執行 • ch11> gcc bubblesort.c -o bubblesort.exe <Enter> • ch11> bubblesort.exe <Enter> • Original array : • 12 78 41 15 73 52 • Start bubble sort : • pass #1 • 12 15 78 41 52 73 • pass #2 • 12 15 41 78 52 73 • pass #3 • 12 15 41 52 78 73 • pass #4 • 12 15 41 52 73 78 • After bubble sort : • 12 15 41 52 73 78

  16. 11.4.2 快速排序 • 在氣泡排序時,比較相鄰的兩項再決定是否互換資料,互換資料的次數相當頻繁,因而降低排序的速度。 • 快速排序也屬於互換排序,它是公元一九六二年由 C.A.R.Hoare 所發展出來的演算法,它較氣泡排序快速,因其互換資料次數較少,因此排序速度較快。 • 快速排序每一次從陣列裡選出一個元素當基準(pivot),該基準也稱為標竿(pole),將陣列元素分為三群:標竿左群、標竿、標竿右群。讓標竿左群所有元素值均比標竿值小,讓標竿右群所有元素值均大於或等於標竿值,如此標竿就處於正確位置了。 • 標竿左群元素個數若小於或等於指定的數量,例如 MINSIZE=8,就直接使用插入法排序,元素個數若大於指定的數量,就繼續快速排序。標竿右群也做同樣的處理。

  17. 找出pivot標竿元素 第一個目標要找出標竿元素。若左邊的值 k[L] 大於 k[M] 中間的值,則其值互換。若左邊的值 k[L] 大於 k[R] 右邊的值,則其值互換。若中間的值 k[M] 大於 k[R] 右邊的值,則其值互換。然後左邊值與中間值互換,這時左邊值就是基準的標竿了。如下圖所示。

  18. 標竿63的正確位置 第二個目標要決定標竿元素的正確位置。從標竿右邊的元素 22 開始,往右找尋大於或等於標竿的元素,找到 98,其位置為 i=4。接著從右邊界 R 元素開始,往左找尋比標竿小的元素,找到 46,其位置為 j=10,這兩個元素互換。

  19. 快速排序完成 標竿左群含四個元素,分別為 {k[1],...,k[4]},其值分別為 {23,22,15,46},其個數 4 小於 MINSIZE(8),因此直接插入排序成 {15,22,23,46}。標竿右群含七個元素,分別為 {k[6],...,k[12]},其值分別為 {88,75,86,77,98,85,79},其個數 7 小於 MINSIZE(8),因此直接插入排序成 {75,77,79,85,86,88,98}。

  20. 編譯執行 • ch11> gcc quicksort.c -o quicksort.exe <Enter> • ch11> quicksort.exe <Enter> • original k[] array : • 79 22 15 98 88 63 75 86 77 46 85 23 • pivot subscript=5, k[5]=63 • 23 22 15 46 63 88 75 86 77 98 85 79 • k[] array after quickSort() : • 15 22 23 46 63 75 77 79 85 86 88 98

More Related