第7章排序

Download Report

Transcript 第7章排序

第七章 排序
課前指引
「排序」(Sorting)是指將一群資料,按特定規則調換位置,
使資料具有某種次序關係(遞增或遞減),例如資料庫內可針對
某一欄位進行排序,而此欄位稱為「鍵(key)」,欄位裡面的值
我們稱之為「鍵值(key value)」。
章節大綱
7-1 排序簡介
7-2 內部排序法
7-3 外部排序法
備註:可依進度點選小節
7-1 排序簡介
在排序的過程中,資料的移動方式可分為
「直接移動」及「邏輯移動」兩種。
「直接移動」是直接交換儲存資料的位置。
「邏輯移動」並不會移動資料儲存位置,僅改變
指向這些資料的輔助指標的值。
直接移動排序
邏輯移動排序
3
7-1 排序簡介
排序的分類
就排序法的選擇來說,當資料量相當大時,排序
演算法所花費的時間就顯得相當重要;一個排序
法是否為一種有效率(Efficiency)的排序法,取
決於其時間複雜度,而時間複雜度的決定因素則
是排序過程中資料的交換次數及比較次數的多寡。
排序前:21
排序後:81
34
77
45
56
56
45
77
34
81
21
這種排序的時間複雜度就是最壞情況
4
7-1
排序簡介
時間複雜度
最好情況(Best Case)
一次遞增排序所使用的時間複雜度就是資料已完成排序,
例如原本資料已經完成遞增排序了,如果再進行最好情
況。
最壞情況(Worst Case)
指每一鍵值均須重新排列,簡單的例子如原本為遞增排
序重新排序成為遞減,就是最壞情況。
平均情況(Average Case)
空間複雜度就是指演算法在執行過程所需付出的額外記
憶體空間,排序法所使用到的額外空間愈少,它的空間
複雜度就愈佳。
5
7-2 內部排序法
穩定的排序
指資料在經過排序後,兩個相同鍵值的記錄仍然
保持原來的次序,如下例中30左的原始位置在30
右的左邊(所謂30左及30右是指相同鍵值一個在
左一個在右),穩定的排序(Stable Sort)後7左
仍應在7右的左邊,不穩定排序則有可能30左會跑
到30右的右邊去:
原始資料順序:
穩定的排序: 10
不穩定的排序:
30左
21
10
10
30左
21
65
30右
30右
30右
65
30左
21
65
6
7-2 內部排序法
氣泡排序法
又稱為交換排序法,是由觀察水中氣泡變化構思
而成,原理是由第一個元素開始,比較相鄰元素
大小,若大小順序有誤,則對調後再進行下一個
元素的比較,就彷彿氣泡逐漸由水底逐漸冒升到
水面上一樣。
以下排序利用 55、23、87、62、16數列的排序過
程,可以清楚知道氣泡排序法的演算流程:
• 由小到大排序:
7
7-2 內部排序法
• 第一次掃瞄會先拿第一個元素55和第二個元素23作比較,
如果第二個元素小於第一個元素,則作交換的動作。
• 接著拿55和87作比較,就這樣一直比較並交換,到第4
次比較完後即可確定最大值在陣列的最後面。
8
7-2 內部排序法
• 第二次掃瞄亦從頭比較起,但因最後一個元素在第一次
掃瞄就已確定是陣列最大值,故只需比較3次即可把剩
餘陣列元素的最大值排到剩餘陣列的最後面。
9
7-2 內部排序法
• 第三次掃瞄完,完成三個值的排序
• 第四次掃瞄完,即可完成所有排序
由此可知5個元素的氣泡排序法必須執行5-1次掃
瞄,第一次掃瞄需比較5-1次,共比較4+3+2+1=10
次
10
7-2 內部排序法
範例 7.2.1
數列(43,35,12,9,3,99)經由氣泡排序法(Bubble
Sort)由小到大排序,在執行時前三次(Swap)的結
果各為何?
解答
第一次交換的結果為(35,43,12,9,3,99)
第二次交換的結果為(35,12,43,9,3,99)
第三次交換的結果為(35,12,9,43,3,99)
11
7-2 內部排序法
氣泡法分析
1.最壞清況及平均情況均需比較:(n-1)+(n-2)+(n3)+…+3+2+1=n(n-1)/2 次;時間複雜度為O(n2),最好情
況只需完成一次掃瞄,發現沒有做交換的動作則表示已經
排序完成,所以只做了n-1次比較,時間複雜度為O(n)。
2.由於氣泡排序為相鄰兩者相互比較對調,並不會更改其
原本排列的順序,所以是穩定排序法。
3.只需一個額外的空間,所以空間複雜度為最佳。
4.此排序法適用於資料量小或有部份資料已經過排序。
12
7-2 內部排序法
範例 7.2.2
請設計一Java程式,並使用氣泡排序法來將以下
的數列排序,並輸出逐次排序的結果:
6,5,9,7,2,8
13
7-2 內部排序法
範例 7.2.3
以上範例7.2.2程式可以看出氣泡排序法有個缺點,
就是不管資料是否已排序完成都固定會執行n(n1)/2次。
請設計一修改後的Java程式,可以藉由在程式中
加入判斷式來判斷何時可以提前中斷程式,又可
得到正確的資料,來增加程式執行效能。
14
7-2 內部排序法
15
7-2 內部排序法
選擇排序法
以下利用55、23、87、62、16數列的由小到大排
序過程,來說明選擇排序法的演算流程:
1.首先找到此數列中最小值後與第一個元素交換:
2.從第二個值找起,找到此數列中(不包含第一個)的最
小值,再和第二個值交換:
16
7-2 內部排序法
3.從第三個值找起,找到此數列中(不包含第一、二個)
的最小值,再和第三個值交換:
4.從第四個值找起,找到此數列中(不包含第一、二、三
個)的最小值,再和第四個值交換,則此排序完成:
17
7-2 內部排序法
選擇法分析
1.無論是最壞清況、最佳情況及平均情況都需要找到最
大值(或最小值),因此其比較次數為:(n-1)+(n-2)+(n3)+…+3+2+1=
次;時間複雜度為O(n2)
2.由於選擇排序是以最大或最小值直接與最前方未排序
的鍵值交換,資料排列順序很有可能被改變,故不是穩
定排序法。
3.只需一個額外的空間,所以空間複雜度為最佳。
4.此排序法適用於資料量小或有部份資料已經過排序。
18
7-2 內部排序法
範例 7.2.4
請設計一Java程式,並使用選擇排序法來將以下
的數列排序:
9,7,5,3,4,6
19
7-2 內部排序法
插入排序法
是將陣列中的元素,逐一與已排序好的資料作比
較,如前兩個元素先排好,再將第三個元素插入
適當的位置,所以這三個元素仍然是已排序好,
接著再將第四個元素加入,重覆此步驟,直到排
序完成為止。
可以看做是在一串有序的記錄R1、R2…Ri,插入
新的記錄R,使得i+1個記錄排序妥當。
20
7-2 內部排序法
以下我們利用55、23、87、62、16數列的由小到
大排序過程,來說明插入排序法的演算流程。
下圖中,在步驟二,以23為基準與其他元素比較
後,放到適當位置(55的前面),步驟三則拿87與
其他兩個元素比較,接著62在比較完前三個數後
插入87的前面…將最後一個元素比較完後即完成
排序:
21
7-2 內部排序法
插入法分析
1.最壞及平均清況需比較(n-1)+(n-2)+(n-3)+…+3+2+1=
次;時間複雜度為O(n2),最好情況時間複雜度為
:O(n)
2.插入排序是穩定排序法。
3.只需一個額外的空間,所以空間複雜度為最佳。
4.此排序法適用於大部份資料已經過排序或已排序資料
庫新增資料後進行排序。
5.插入排序法會造成資料的大量搬移,所以建議在鏈結
串列上使用。
22
7-2 內部排序法
範例 7.2.5
請設計一Java程式,自行輸入6個數值,並使用插
入排序法來加以排序。
23
7-2 內部排序法
謝耳排序法
是D. L. Shell 在1959年7月所發明的一種排序法,
可以減少插入排序法中資料搬移的次數,以加速
排序進行。
排序的原則是將資料區分成特定間隔的幾個小區
塊,以插入排序法排完區塊內的資料後再漸漸減
少間隔的距離。
以下我們仍然利用63、92、27、36、45、71、58、
7數列的由小到大排序過程,來說明插入排序法的
演算流程:
24
7-2 內部排序法
• 首先將所有資料分成Y:(8div2)即Y=4,稱為劃分數。
請注意!劃分數不一定要是2,質數是最好。但為演算
法方便,所以我們習慣選2。則一開始的間隔設定為
8/2區隔成:
• 如此一來可得到四個區塊分別是:
(6.4)(9.7)(2.5)(3.1)再各別用插入排序法排序成為:
(4.6)(7.9)(2.5)(1.3)
• 接著再縮小間隔為(8/2)/2成
25
7-2 內部排序法
• (4.2.6.5)(7.1.9.3)分別用插入排序法後得到:
• 最後再以((8/2)/2)/2的間距做插入排序,也就是每一
個元素進行排序得到最後的結果:
謝耳法分析
1.任何情況的時間複雜度均為O(n3/2)。
2.謝耳排序法和插入排序法一樣,都是穩定排序。
3.只需一個額外空間,所以空間複雜度是最佳。
4.此排序法適用於資料大部份都已排序完成的情況。
26
7-2 內部排序法
範例 7.2.6
請設計一Java程式,自行輸入8個數值,並使用謝
耳排序法來加以排序。
27
7-2 內部排序法
合併排序法
通常是外部儲存裝置最常用的排序方法,工作原
理乃是針對已排序好的二個或二個以上的檔案,
經由合併的方式,將其組合成一個大的且已排序
好的檔案。步驟如下:
1.將N個長度為1的鍵值成對地合併成N/2個長度為2的鍵
值組。
2.將N/2個長度為2的鍵值組成對地合併成N/4個長度為4
的鍵值組。
3.將鍵值組不斷地合併,直到合併成一組長度為N的鍵
值組為止。
28
7-2 內部排序法
合併排序法的基本演算流程
以條列的方式將步驟整理如下:
1.將N個長度為1的檔案合併成N/2個已排序妥當且長度為2
的檔案。
2.將N/2個長度為2的檔案合併成N/4個已排序妥當且長度為
4的檔案。
3.將N/4個長度為4的檔案合併成N/8個已排序妥當且長度為
8的檔案。
4.將N/2i-1個長度為2i-1的檔案合併成N/2i個已排序妥當且長
度為2i的檔案。
29
7-2 內部排序法
快速排序法
又稱分割交換排序法,是目前公認最佳的排序法,
也是使用切割征服(Divide and Conquer)的方式,
會先在資料中找到一個隨機會自行設定一個虛擬
中間值,並依此中間值將所有打算排序的資料分
為兩部份。
假設有n筆R1、R2、R3…Rn記錄,其鍵值為k1、k2、
k3…kn:
①先假設K的值為第一個鍵值。
②由左向右找出鍵值Ki,使得Ki>K。
③由右向左找出鍵值Kj使得Kj<K。
④如果i<j,那麼Ki與Kj互換,並回到步驟②。
⑤若i≧j則將K與Kj交換,並以j為基準點分割成左右部份。然後再針
對左右兩邊進行步驟①至⑤,直到左半邊鍵值=右半邊鍵值為止。
30
7-2 內部排序法
快速排序法將下列資料的排序過程
因為i<j故交換Ki與Kj,然後繼續比較:
因為i<j故交換Ki與Kj,然後繼續比較:
31
7-2 內部排序法
因為ij故交換K與Kj,並以j為基準點分割成左右
兩半:
由上述這幾個步驟,各位可以將小於鍵值K放在左
半部;大於鍵值K放在右半部,依上述的排序過程,
針對左右兩部份分別排序。過程如下:
32
7-2 內部排序法
快速法分析
1.在最快及平均情況下,時間複雜度為O(nlog2n)。最壞
情況就是每次挑中的中間值不是最大就是最小,其時間
複雜度為O(n2)。
2.快速排序法不是穩定排序法。
3.在最差的情況下,空間複雜度為O(n),而最佳情況為
O(log2n)。
4.快速排序法是平均執行時間最快的排序法。
33
7-2 內部排序法
範例 7.2.7
請設計一Java程式,可輸入陣列的個數,並使用
亂數產生數值,試利用快速排序法加以排序。
34
7-2 內部排序法
堆積排序法
堆積排序法使用到了二元樹的技巧,它是利用堆
積樹來完成排序。堆積是一種特殊的二元樹,可
分為最大堆積樹及最小堆積樹兩種。而最大堆積
樹滿足以下3個條件:
1.它是一個完整二元樹。
2.所有節點的值都大於或等於它左右子節點的值。
3.樹根是堆積樹中最大的。
最小堆積樹則具備以下3個條件:
1.它是一個完整二元樹。
2.所有節點的值都小於或等於它左右子節點的值。
3.樹根是堆積樹中最小的。
35
7-2 內部排序法
範例
將利用堆積排序法針對34、19、40、14、57、17、
4、43的排序過程示範如下
依下圖數字順序建立完整二元樹
36
7-2 內部排序法
建立堆積樹
將57自樹根移除,重新建立堆積樹
將43自樹根移除,重新建立堆積樹
37
7-2 內部排序法
將40自樹根移除,重新建立堆積樹
將34自樹根移除,重新建立堆積樹
將19自樹根移除,重新建立堆積樹
38
7-2 內部排序法
將17自樹根移除,重新建立堆積樹
將14自樹根移除,重新建立堆積樹
最後將4自樹根移除。得到的排序結果為
57、43、40、34、19、17、14、4
堆積法分析
1.在所有情況下,時間複雜度均為O(nlogn)。
2.堆積排序法不是穩定排序法。
3.只需要一額外的空間,空間複雜度為O(1)。
39
7-2 內部排序法
範例 7.2.8
請設計一Java程式,並使用堆積排序法來將一數
列排序。
40
7-2 內部排序法
基數排序法
基數排序法依比較的方向可分為最有效鍵優先
(Most Significant Digit First:MSD)和最無效
鍵優先(Least Significant Digit First:LSD)兩
種。
底下的範例以LSD將三位數的整數資料來加以排序,
它是依個位數、十位數、百位數來進行排序。以
下最無效鍵優先(LSD)例子的說明,便可清楚的知
道它的動作原理:
原始資料:
41
7-2 內部排序法
• 步驟一:把每個整數依其個位數字放到串列中
• 合併後成為
• 步驟二:再依其十位數字,依序放到串列中:
• 合併後成為
42
7-2 內部排序法
• 步驟三:再依其百位數字,依序放到串列中
• 最後合併即完成排序
43
7-2 內部排序法
範例 7.2.9
請設計一Java程式,可自行輸入數值陣列的個數,
並使用基數排序法來排序。
44
7-3外部排序法
直接合併排序法
直接合併排序法(Direct Merge Sort)是外部儲存
裝置最常用的排序方法。它可以分為兩個步驟:
1.將欲排序的檔案分為幾個可以載入記憶體空間大小的小檔案,
再使用內部排序法將各檔案內的資料排序。
2.將第一步驟所建立的小檔案每二個合併成一個檔案。兩兩合併後
,把所有檔案合併成一個檔案後就可以完成排序了。
例如:把一個檔案分成6個小檔案:
45
7-3外部排序法
小檔案都完成排序後,兩兩合併成一個較大的檔
案,最後再合併成一個檔案即可完成。
46
7-3外部排序法
範例 7.3.1
請設計一Java程式,直接把兩個已經排序好的檔
案合併與排序成一個檔案。
data1.dat:1 3 4 5
dara2.dat:2 6 7 9
47
7-3外部排序法
範例 7.3.2
請設計一Java程式,利用合併排序法將一檔案拆
成兩個或兩個以上的行程(runs),再利用上一個
範例程式所介紹的方法合併成一個檔案。
48
7-3外部排序法
k路合併法
描述利用3路合併(3-way merge)來處理27個行程
(Runs)的示意圖。
使用k-way合併的原意是希望減少輸出入時間,但
合併k個行程前要決定下一筆輸出的排序資料,必
須作k-1次比較才可以得到答案。
49
7-3外部排序法
多相合併法
下圖共有21個runs,使用2-way合併及3個磁帶T1、
T2、T3來進行合併,假設這21個行程(已排序完畢,
且令其長度為1)的表示方為Sn,其中S為行程大小,
n為長度相同run的個數。例如8個runs且長度為2,
可表示成28。
50
7-3外部排序法
使用2-way及3個磁碟的多項合併
51
本章結束
Q&A討論時間
52