540 likes | 700 Views
親愛的老師您好. 感謝您選用本書作為授課教材,博碩文化準備本書精選簡報檔,特別摘錄重點提供給您授課專用。 說明: 1 、本教具為非賣品,不得作為商業之用。 2 、本教具僅授權使用原著作為授課教材之教師作為教學或研究等學術用途。 3 、本教具未授權提供學生任何拷貝、影印、引用、翻印等行為。 4 、教師若需申請網站或內容授權,可透過您的博碩業務協助處理,謝謝。. 博碩文化: 總公司:台北縣汐止市新台五路一段 94 號 6 樓 A 棟 電話: (02) 2696-2869 分機 313 傳真: (02) 2696-2867
E N D
親愛的老師您好 感謝您選用本書作為授課教材,博碩文化準備本書精選簡報檔,特別摘錄重點提供給您授課專用。 說明: 1、本教具為非賣品,不得作為商業之用。 2、本教具僅授權使用原著作為授課教材之教師作為教學或研究等學術用途。 3、本教具未授權提供學生任何拷貝、影印、引用、翻印等行為。 4、教師若需申請網站或內容授權,可透過您的博碩業務協助處理,謝謝。 博碩文化: 總公司:台北縣汐止市新台五路一段94號6樓A棟 電話:(02) 2696-2869 分機 313 傳真:(02) 2696-2867 網址:www.drmaster.com.tw客服信箱:school@drmaster.com.tw 出書提案信箱 schoolbook@drmaster.com.tw
資料結構 請老師填入姓名主講 課本:圖解資料結構使 用Java 博碩文化出版發行
第七章 排序 課前指引 「排序」(Sorting)是指將一群資料,按特定規則調換位置,使資料具有某種次序關係(遞增或遞減),例如資料庫內可針對某一欄位進行排序,而此欄位稱為「鍵(key)」,欄位裡面的值我們稱之為「鍵值(key value)」
章節大綱 7-1 排序簡介 7-2 內部排序法 7-3 外部排序法 備註:可依進度點選小節
7-1 排序簡介 在排序的過程中,資料的移動方式可分為「直接移動」及「邏輯移動」兩種。 「直接移動」是直接交換儲存資料的位置 「邏輯移動」並不會移動資料儲存位置,僅改變指向這些資料的輔助指標的值。 直接移動排序 邏輯移動排序
排序的分類 就排序法的選擇來說,當資料量相當大時,排序演算法所花費的時間就顯得相當重要;一個排序法是否為一種有效率(Efficiency)的排序法,取決於其時間複雜度,而時間複雜度的決定因素則是排序過程中資料的交換次數及比較次數的多寡。 7-1 排序簡介 這種排序的時間複雜度就是最壞情況 排序前:21 34 45 56 77 81 排序後:81 77 56 45 34 21
7-1 排序簡介 • 時間複雜度 • 最好情況(Best Case) • 一次遞增排序所使用的時間複雜度就是資料已完成排序,例如原本資料已經完成遞增排序了,如果再進行最好情況。 • 最壞情況(Worst Case) • 指每一鍵值均須重新排列,簡單的例子如原本為遞增排序重新排序成為遞減,就是最壞情況。 • 平均情況(Average Case) • 空間複雜度就是指演算法在執行過程所需付出的額外記憶體空間,排序法所使用到的額外空間愈少,它的空間複雜度就愈佳。
7-2 內部排序法 穩定的排序 指資料在經過排序後,兩個相同鍵值的記錄仍然保持原來的次序,如下例中30左的原始位置在30右的左邊(所謂30左及30右是指相同鍵值一個在左一個在右),穩定的排序(Stable Sort)後7左仍應在7右的左邊,不穩定排序則有可能30左會跑到30右的右邊去: 原始資料順序: 30左 10 65 30右 21 穩定的排序: 10 21 30左30右 65 不穩定的排序: 10 21 30右 30左 65
氣泡排序法 又稱為交換排序法,是由觀察水中氣泡變化構思而成,原理是由第一個元素開始,比較相鄰元素大小,若大小順序有誤,則對調後再進行下一個元素的比較,就彷彿氣泡逐漸由水底逐漸冒升到水面上一樣。 以下排序利用 55、23、87、62、16數列的排序過程,可以清楚知道氣泡排序法的演算流程: 由小到大排序: 7-2 內部排序法
第一次掃瞄會先拿第一個元素55和第二個元素23作比較,如果第二個元素小於第一個元素,則作交換的動作。第一次掃瞄會先拿第一個元素55和第二個元素23作比較,如果第二個元素小於第一個元素,則作交換的動作。 接著拿55和87作比較,就這樣一直比較並交換,到第4次比較完後即可確定最大值在陣列的最後面。 7-2 內部排序法
第二次掃瞄亦從頭比較起,但因最後一個元素在第一次掃瞄就已確定是陣列最大值,故只需比較3次即可把剩餘陣列元素的最大值排到剩餘陣列的最後面。 7-2 內部排序法
第三次掃瞄完,完成三個值的排序 第四次掃瞄完,即可完成所有排序 由此可知5個元素的氣泡排序法必須執行5-1次掃瞄,第一次掃瞄需比較5-1次,共比較4+3+2+1=10次 7-2 內部排序法
範例 7.2.1 數列(43,35,12,9,3,99)經由氣泡排序法(Bubble Sort)由小到大排序,在執行時前三次(Swap)的結果各為何? 7-2 內部排序法 解答 第一次交換的結果為(35,43,12,9,3,99) 第二次交換的結果為(35,12,43,9,3,99) 第三次交換的結果為(35,12,9,43,3,99)
7-2 內部排序法 氣泡法分析 1.最壞清況及平均情況均需比較:(n-1)+(n-2)+(n-3)+…+3+2+1=n(n-1)/2 次;時間複雜度為O(n2),最好情況只需完成一次掃瞄,發現沒有做交換的動作則表示已經排序完成,所以只做了n-1次比較,時間複雜度為O(n)。 2.由於氣泡排序為相鄰兩者相互比較對調,並不會更改其原本排列的順序,所以是穩定排序法。 3.只需一個額外的空間,所以空間複雜度為最佳。 4.此排序法適用於資料量小或有部份資料已經過排序。
7-2 內部排序法 範例 7.2.2 請設計一Java程式,並使用氣泡排序法來將以下的數列排序,並輸出逐次排序的結果: 6,5,9,7,2,8
7-2 內部排序法 範例 7.2.3 以上範例7.2.2程式可以看出氣泡排序法有個缺點,就是不管資料是否已排序完成都固定會執行n(n-1)/2次。 請設計一修改後的Java程式,可以藉由在程式中加入判斷式來判斷何時可以提前中斷程式,又可得到正確的資料,來增加程式執行效能。
7-2 內部排序法 選擇排序法 以下利用55、23、87、62、16數列的由小到大排序過程,來說明選擇排序法的演算流程: 1.首先找到此數列中最小值後與第一個元素交換: 2.從第二個值找起,找到此數列中(不包含第一個)的最小值,再和第二個值交換:
7-2 內部排序法 3.從第三個值找起,找到此數列中(不包含第一、二個)的最小值,再和第三個值交換: 4.從第四個值找起,找到此數列中(不包含第一、二、三個)的最小值,再和第四個值交換,則此排序完成:
7-2 內部排序法 選擇法分析 1.無論是最壞清況、最佳情況及平均情況都需要找到最大值(或最小值),因此其比較次數為:(n-1)+(n-2)+(n- 3)+…+3+2+1= 次;時間複雜度為O(n2) 2.由於選擇排序是以最大或最小值直接與最前方未排序的鍵值交換,資料排列順序很有可能被改變,故不是穩定排序法。 3.只需一個額外的空間,所以空間複雜度為最佳。 4.此排序法適用於資料量小或有部份資料已經過排序。
7-2 內部排序法 範例 7.2.4 請設計一Java程式,並使用選擇排序法來將以下的數列排序: 9,7,5,3,4,6
7-2 內部排序法 插入排序法 是將陣列中的元素,逐一與已排序好的資料作比較,如前兩個元素先排好,再將第三個元素插入適當的位置,所以這三個元素仍然是已排序好,接著再將第四個元素加入,重覆此步驟,直到排序完成為止。 可以看做是在一串有序的記錄R1、R2…Ri,插入新的記錄R,使得i+1個記錄排序妥當。
7-2 內部排序法 以下我們利用55、23、87、62、16數列的由小到大排序過程,來說明插入排序法的演算流程。 下圖中,在步驟二,以23為基準與其他元素比較後,放到適當位置(55的前面),步驟三則拿87與其他兩個元素比較,接著62在比較完前三個數後插入87的前面…將最後一個元素比較完後即完成排序:
7-2 內部排序法 插入法分析 1.最壞及平均清況需比較(n-1)+(n-2)+(n-3)+…+3+2+1= 次;時間複雜度為O(n2),最好情況時間複雜度為 :O(n) 2.插入排序是穩定排序法。 3.只需一個額外的空間,所以空間複雜度為最佳。 4.此排序法適用於大部份資料已經過排序或已排序資料庫新增資料後進行排序。 5.插入排序法會造成資料的大量搬移,所以建議在鏈結串列上使用。
7-2 內部排序法 範例 7.2.5 請設計一Java程式,自行輸入6個數值,並使用插入排序法來加以排序。
7-2 內部排序法 謝耳排序法 是D. L. Shell 在1959年7月所發明的一種排序法,可以減少插入排序法中資料搬移的次數,以加速排序進行。 排序的原則是將資料區分成特定間隔的幾個小區塊,以插入排序法排完區塊內的資料後再漸漸減少間隔的距離。 以下我們仍然利用63、92、27、36、45、71、58、7數列的由小到大排序過程,來說明插入排序法的演算流程:
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成
7-2 內部排序法 (4.2.6.5)(7.1.9.3)分別用插入排序法後得到: 最後再以((8/2)/2)/2的間距做插入排序,也就是每一個元素進行排序得到最後的結果: 謝耳法分析 1.任何情況的時間複雜度均為O(n3/2)。 2.謝耳排序法和插入排序法一樣,都是穩定排序。 3.只需一個額外空間,所以空間複雜度是最佳。 4.此排序法適用於資料大部份都已排序完成的情況。
7-2 內部排序法 範例 7.2.6 請設計一Java程式,自行輸入8個數值,並使用謝耳排序法來加以排序。
7-2 內部排序法 合併排序法 通常是外部儲存裝置最常用的排序方法,工作原理乃是針對已排序好的二個或二個以上的檔案,經由合併的方式,將其組合成一個大的且已排序好的檔案。步驟如下: 1.將N個長度為1的鍵值成對地合併成N/2個長度為2的鍵值組。 2.將N/2個長度為2的鍵值組成對地合併成N/4個長度為4的鍵值組。 3.將鍵值組不斷地合併,直到合併成一組長度為N的鍵值組為止。
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的檔案。
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為基準點分割成左右部份。然後再針對左右兩邊進行步驟①至⑤,直到左半邊鍵值=右半邊鍵值為止。
7-2 內部排序法 快速排序法將下列資料的排序過程 因為i<j故交換Ki與Kj,然後繼續比較: 因為i<j故交換Ki與Kj,然後繼續比較:
7-2 內部排序法 因為ij故交換K與Kj,並以j為基準點分割成左右兩半: 由上述這幾個步驟,各位可以將小於鍵值K放在左半部;大於鍵值K放在右半部,依上述的排序過程,針對左右兩部份分別排序。過程如下:
7-2 內部排序法 快速法分析 1.在最快及平均情況下,時間複雜度為O(nlog2n)。最壞情況就是每次挑中的中間值不是最大就是最小,其時間複雜度為O(n2)。 2.快速排序法不是穩定排序法。 3.在最差的情況下,空間複雜度為O(n),而最佳情況為O(log2n)。 4.快速排序法是平均執行時間最快的排序法。
7-2 內部排序法 範例 7.2.7 請設計一Java程式,可輸入陣列的個數,並使用亂數產生數值,試利用快速排序法加以排序。
7-2 內部排序法 堆積排序法 堆積排序法使用到了二元樹的技巧,它是利用堆積樹來完成排序。堆積是一種特殊的二元樹,可分為最大堆積樹及最小堆積樹兩種。而最大堆積樹滿足以下3個條件: 最小堆積樹則具備以下3個條件: 1.它是一個完整二元樹。 2.所有節點的值都大於或等於它左右子節點的值。 3.樹根是堆積樹中最大的。 1.它是一個完整二元樹。 2.所有節點的值都小於或等於它左右子節點的值。 3.樹根是堆積樹中最小的。
7-2 內部排序法 範例 將利用堆積排序法針對34、19、40、14、57、17、4、43的排序過程示範如下 依下圖數字順序建立完整二元樹
7-2 內部排序法 建立堆積樹 將57自樹根移除,重新建立堆積樹 將43自樹根移除,重新建立堆積樹
7-2 內部排序法 將40自樹根移除,重新建立堆積樹 將34自樹根移除,重新建立堆積樹 將19自樹根移除,重新建立堆積樹
7-2 內部排序法 將17自樹根移除,重新建立堆積樹 將14自樹根移除,重新建立堆積樹 最後將4自樹根移除。得到的排序結果為 57、43、40、34、19、17、14、4 堆積法分析 1.在所有情況下,時間複雜度均為O(nlogn)。 2.堆積排序法不是穩定排序法。 3.只需要一額外的空間,空間複雜度為O(1)。
7-2 內部排序法 範例 7.2.8 請設計一Java程式,並使用堆積排序法來將一數列排序。
7-2 內部排序法 基數排序法 基數排序法依比較的方向可分為最有效鍵優先(Most Significant Digit First:MSD)和最無效鍵優先(Least Significant Digit First:LSD)兩種。 底下的範例以LSD將三位數的整數資料來加以排序,它是依個位數、十位數、百位數來進行排序。以下最無效鍵優先(LSD)例子的說明,便可清楚的知道它的動作原理: 原始資料:
7-2 內部排序法 步驟一:把每個整數依其個位數字放到串列中 合併後成為 步驟二:再依其十位數字,依序放到串列中: 合併後成為
7-2 內部排序法 步驟三:再依其百位數字,依序放到串列中 最後合併即完成排序
7-2 內部排序法 範例 7.2.9 請設計一Java程式,可自行輸入數值陣列的個數,並使用基數排序法來排序。
7-3外部排序法 直接合併排序法 直接合併排序法(Direct Merge Sort)是外部儲存裝置最常用的排序方法。它可以分為兩個步驟: 例如:把一個檔案分成6個小檔案: 1.將欲排序的檔案分為幾個可以載入記憶體空間大小的小檔案,再使用內部排序法將各檔案內的資料排序。 2.將第一步驟所建立的小檔案每二個合併成一個檔案。兩兩合併後,把所有檔案合併成一個檔案後就可以完成排序了。
7-3外部排序法 小檔案都完成排序後,兩兩合併成一個較大的檔案,最後再合併成一個檔案即可完成。
7-3外部排序法 範例 7.3.1 請設計一Java程式,直接把兩個已經排序好的檔案合併與排序成一個檔案。 data1.dat:1 3 4 5 dara2.dat:2 6 7 9
7-3外部排序法 範例 7.3.2 請設計一Java程式,利用合併排序法將一檔案拆成兩個或兩個以上的行程(runs),再利用上一個範例程式所介紹的方法合併成一個檔案。