20
11.3 插插插插 • 插插插插insertion sorting 插插插插插插 插插插插插插插插插插插插插插插插 插插插插插插 插插插插 插插插 ,一, 插插插 插插插插插插插插插 插插插插插插插插插插插插 插插插插插 ,,, 插插插 插插插插插 插插插插 插插插插插插插插插插插插插插插插 一,一。 • 插插插插插插插插插插插插插插 插插插插插插插插插 :( shell 插插插插

11.3 插入排序

Embed Size (px)

DESCRIPTION

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

Citation preview

Page 1: 11.3  插入排序

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

Page 2: 11.3  插入排序

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

Page 3: 11.3  插入排序

直接插入排序舉例

Page 4: 11.3  插入排序

直接插入排序函式• 直接插入排序函式原型宣告如下: • void insertSort(int k[], int L, int R)

• 需要三個引數,陣列 k[] ,左範圍註標 L ,右範圍註標 R 。 • 先將標的元素存入 kk ,其後的元素逐一與 kk 比較,若較 kk 大則搬移至右一位,空出本身位置,直到較 kk 小時,就找到 kk 的位置,置入 kk 值。

Page 5: 11.3  插入排序

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

Page 6: 11.3  插入排序

11.3.2 謝耳排序• 謝耳排序法( Shell sort )是記念創造者 Donald L. Shel

l 先生,是一款直接插入排序法的改良版本,也是屬於快速排序法。 • 謝耳排序法將 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] 。

Page 7: 11.3  插入排序

謝耳排序分 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] ,且是惟一的一段。

Page 8: 11.3  插入排序

謝耳排序舉例

Page 9: 11.3  插入排序

謝耳排序• 謝耳排序函式原型宣告如下: • 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] ,以插入排序法排序,稱為第三回合,完成排序。

Page 10: 11.3  插入排序

編譯執行• 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

Page 11: 11.3  插入排序

11.4 互換排序• 排序的第三類別屬於互換排序( exchang

e ),本小節說明氣泡排序法( bubble sort )以及快速排序法( quick sort )。

Page 12: 11.3  插入排序

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

Page 13: 11.3  插入排序

氣泡排序法舉例

Page 14: 11.3  插入排序

• 上圖是六個資料項 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

Page 15: 11.3  插入排序

編譯執行• 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

Page 16: 11.3  插入排序

11.4.2 快速排序• 在氣泡排序時,比較相鄰的兩項再決定是否互換資料,互換資料的次數相當頻繁,因而降低排序的速度。• 快速排序也屬於互換排序,它是公元一九六二年由 C.A.R.

Hoare 所發展出來的演算法,它較氣泡排序快速,因其互換資料次數較少,因此排序速度較快。• 快速排序每一次從陣列裡選出一個元素當基準( pivot ),該基準也稱為標竿( pole ),將陣列元素分為三群:標竿左群、標竿、標竿右群。讓標竿左群所有元素值均比標竿值小,讓標竿右群所有元素值均大於或等於標竿值,如此標竿就處於正確位置了。 • 標竿左群元素個數若小於或等於指定的數量,例如 MINSI

ZE=8 ,就直接使用插入法排序,元素個數若大於指定的數量,就繼續快速排序。標竿右群也做同樣的處理。

Page 17: 11.3  插入排序

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

Page 18: 11.3  插入排序

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

Page 19: 11.3  插入排序

快速排序完成標竿左群含四個元素,分別為 {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} 。

Page 20: 11.3  插入排序

編譯執行• 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