• 沒有找到結果。

切割與征服

N/A
N/A
Protected

Academic year: 2021

Share "切割與征服"

Copied!
27
0
0

加載中.... (立即查看全文)

全文

(1)

國立聯合大學

國立聯合大學 資訊管理學系資訊管理學系陳士杰老師陳士杰老師

Course 5

切割與征服

Divide-and-Conquer

(2)

Outlines

‹

本章重點

„

Divide-and-Conquer策略的描述

„

Binary Search

„

Merge Sort

„

Divide-and-Conquer 的技巧

„

Quick Sort

„

Strassen‘s 矩陣相乘演算法

„

何時不能使用 Divide-and-Conquer

(3)

‹

Divide-and-conquer 是一種由上而下 由上而下 (top (top -down) - down) 的解題 方式.

„

它將一個問題切割 切割 (

dividesdivides

) 成兩個或以上的較小問題。較小的問 題通常是原問題的實例。

„

如果較小的問題之解可以容易地獲得,那麼原問題的解可以藉由合 合 併較小問題的答案

併較小問題的答案獲得。

„

如果小問題還是太大以致於不易解決,則可以再被切割成更小的問 題直到切到夠小而易獲得結果為止。

Divide-and-Conquer策略的描述與技巧

(4)

‹

Def:

„

可將母問題切割成較小的問題 較小的問題 (切割),使用相同的解決程序 相同的解決程序加 以處理 (征服)。所有小問題的解可以成為母問題的最後解; 若有 必要,則再將每個小問題的處理結果加以合併,就可以得到最 後的答案。

{

由於使用相同的解決程序處理每個小問題,這一個程序就會被遞 迴呼叫,因此一個遞迴演算法則通常以一個副程式的型式出現,

內部包含一個解決程序與遞迴呼叫。

{

對於具有遞迴關係 遞迴關係的問題,或是一些採用遞迴定義的資料結構,

都適合採用Divide-and-Conquer演算法設計策略

„

最簡潔、易懂

„

效率差 (∵採用遞迴設計)

(5)

‹

下列兩種情況是適合使用Divide-and-Conquer設計策略 (也 是遞迴演算法的適用時機):

„

„ 問題本身具有遞迴關係 問題本身具有遞迴關係

{

母問題可被切割成較小的 “ 相同” 問題 相同

{

如: 階乘問題、費氏數問題、河內塔問題、快速排序問題、二 元搜尋問題…等

„

„ 資料結構屬於遞迴定義 資料結構屬於遞迴定義

{

大量的Data Set,在切割後仍為一組具 “ 相同性質” 的Data Set 相同性質

{

如: 二元樹 (Binary Tree)、鏈結串列 (Link List)…等

Divide-and-Conquer使用時機

(6)

遞迴演算法則的設計

1. 找出問題的 終止條件. 終止條件

2. 找出問題本身的 遞迴關係 遞迴關係 ( ( 遞迴呼叫 遞迴呼叫 ) ) .

‹ 技巧:

„

思考遞迴呼叫需要哪些參數?

„

遞迴呼叫的傳回值為何?

„

遞迴呼叫的終止條件為何? 終止傳回何值?

Procedure Recursion_subroutine(Parameter);

{

if (終止條件 終止條件) then Return( );

else Recursion_subroutine(New_parameter Recursion_subroutine(New_parameter) ) ;

}

(7)

Binary Search (二分搜尋)

‹

實施前提:

„

檔案中記錄須事先由小到大 由小到大排序過

„

須由

Random (Random (

或 或

Direct) accessDirect) access

之機制支援 (e.g., Array)

‹

觀念:

„

每次皆與Search範圍的中間記錄 中間記錄進行比較!!

while ( l u )

比較 (k, S[m])

case “=”: found, i = m, return i;

case “<”: uu= m-1;

case “>”: ll= m+1;

recurn 0;

小 大

⎥⎦ ⎥

⎢⎣ ⎢ +

= 2 middle

l u

⎥⎦

⎢⎣⎢ +

= 2 m l u

l m umiddle l m u

S

//找到了

//要找的資料在左半部 //要找的資料在右半部

(8)

分析

‹

利用Time function T(n) = T(n/2) + O(1)

= T(n/2) + c

= (T(n/4 + c)) + c = T(n/4) + 2c

= (T(n/8) + c) + 2c = T(n/8) +3c

= …

= T(n/n) + log

2

n×c

= T(1) + c log

2

n (T(1) = 1, c 為大於 0 的常數)

= 1 + c log

2

n

∴ T(n) = O(log

2

n)

(9)

‹

二元搜尋法的步驟摘要如下。如果x與中間項相同則離開,

否則:

„„

切割 切割 (Divide) (Divide) 該陣列成大約一半大小的兩個子陣列。.

{

如果x小於中間項 小於中間項,選擇左邊的子陣列 左邊的子陣列。如果x大於中間項 大於中間項,則選擇右 右 邊的子陣列

邊的子陣列。

„

藉由判斷x是否在該子陣列中來征服 征服 (Conquer; (Conquer; 或稱解決 solve) ) 該 子陣列。

{

除非該子陣列夠小,否則使用 遞迴來做這件事。 遞迴

„

由子陣列的解答來獲得 獲得 (Obtain) (Obtain) 該陣列的解答。

‹

二元搜尋法是最簡單的一種Divide-and-conquer演算法。因

為原有問題的解答就是較小問題所解出的解答,所以沒有

輸出結果的合併。

(10)

‹

觀念:

„

將兩個已排序過的記錄合併,而得到另一個排序好的記 錄。

‹

可分為兩種類型:

„

Recursive (遞迴)

„

Iterative (迴圈, 非遞迴)

Merge Sort (合併排序)

(11)

Recursive Merge Sort (遞迴合併排序)

‹

將資料量 n 切成 n/2 與 n/2 兩半部,再各自Merge 兩半部 Sort,最後合併兩半部之排序結果即成。

‹

切割資料量 n 的公式為:

‹

[ ]: Run, 已排序好的檔案記錄 已排序好

‹

Run的長度: Run中 記錄個數 記錄個數

⎥⎦ ⎥

⎢⎣ ⎢ + 2

high)

(low

(12)

Stack

第一層切割所有 資訊依序輸入 第二層切割所有

資訊依序輸入 第三層切割所有

資訊依序輸入 第四層切割所有

資訊依序輸入

(13)

Time-Complexity

‹

Avg. / Worst / Best Case: O(n O(n log n) log n)

‹

以Recursive Merge Sort角度:

[說明]:

時間函數: T(n) = T(n/2) + T(n/2) + c×n 時間複雜度求法:

{

{

遞迴樹 遞迴樹

‡

步驟:

‹ 將原本問題照遞迴定義展開

‹ 計算每一層的Cost

‹ 加總每一層的Cost即為所求

{{

數學解法 數學解法

‹

最後合併左右兩半部 合併左右兩半部所花時間

„ ∵ 左、右半部排好之後,各只 剩一個Run,且兩半部各有 兩半部各有

n/2n/2

的資料量,其最後一次合併時 的資料量 的比較次數 “最多 最多 ”為 n/2 + n/2

n/2 + n/2 -1-1

次,即約 n-1 次 (slide 72)

„ ∴時間的表示可為 c

c

× ×

nn

次(∵為 次 線性時間)) 線性時間

左半部遞迴 右半部遞迴

(14)

‹

合併排序法包含了下列的步驟 :

„„

切割 切割 (Divide) (Divide) 該陣列成為兩個具有

nn/2/2

個項目的子陣列。

„„

征服 征服 (Conquer; 或稱解決solve (Conquer )每一個子陣列。 )

{

除非該子陣列夠小,否則使用 遞迴來做這件事。 遞迴

„„

合併 合併 (Combine) (Combine) 所有子陣列的所有解答,以獲得主陣列的解答。

(15)

‹

Divide-and-conquer 的設計策略包含下列的步驟:

„„

切割 切割 (Divide) (Divide) 一個較大的問題以成為一個或多個較小的問題。

„„

征服 征服 (Conquer ; 或稱解決solve (Conquer ) ) 每一個較小的問題。

{

除非問題已經足夠的小,否則使用遞迴 遞迴來解決。

„„

如果需要, 將所有小問題的解答加以合併 如果需要 合併(combine) (combine) ,以獲得原 始問題的解答。

{

需要合併的問題: Merge sort

{

不需要合併的問題: Binary search

Divide-and-Conquer 技巧

(16)

Quick Sort (快速排序)

‹

Avg. case 下,排序最快的algo.

‹

Def:

„

將大且複雜的問題 切成許多獨立的小問題,再加以解決各小問題 切成許多獨立的小問題 後,即可求出問題的Solution。

„

此即 “

Divide-Divide-andand--ConquerConquer

” (切割並征服)的解題策略。

‹

觀念:

„

將第一筆記錄視為Pivot Key (樞紐鍵 (P.K.) ,或稱Control Key),在 Pass 1 (第一回合) 後,可將P.K.置於 “最正確” 的位置上。

„

Ex:

(經過Pass 1)

>

„

把P.K.擺在正確的位置 >為切割 切割的概念 (∴可使用 遞迴) 遞迴

P.K.

P.K.

R

i

R

j

, R

i

.key ≤ P.K. 且 R

j

.key ≥ P.K.

(17)

‹

多顆CPU時的運算過程:

(18)

Time-Complexity

‹

Best Case: O(n O(n log n) log n)

„

P.K.之最正確位置 恰好將資料量 恰好將資料量 均分成二等份 均分成二等份

{

以Multiprocessor來看,2個CPU的工作量相等,工作可同時做 完,沒有誰等誰的問題

[說明]:

時間函數: T(n) = c×n + T(n/2) + T(n/2) 時間複雜度求法:

{{

遞迴樹 遞迴樹

‡

步驟:

‹ 將原本問題照遞迴定義展開

‹ 計算每一層的Cost

‹ 加總每一層的Cost即為所求

{{

數學解法 數學解法

變數

i 與 j 最多花 n 個執行

時間找記錄

(即: 決定P.K.

最正確位置所花時間

)

左半部 右半部

(19)

‹

Worst Case: O(n O(n

22

) )

„

當輸入資料是由大到小 由大到小或 或由小到大 由小到大排好 排好時 ( ( 切割毫無用處 切割毫無用處 ) )

[說明]:

P.K.

P.K.

輸入資料: 輸入資料

:

小 大

輸入資料: 輸入資料

:

大 小

P.K.

[0筆[0

]] [ n-[ n-11筆

]]

P.K.

[0筆[0

]] [ n

[ n--11

筆 筆

]] Pass 1

Pass 1

Pass 1 Pass 1

(20)

‹

Average Case: O(n O(n log n) log n)

[說明]:

⇒ [T(s) T(n s)] cn , T(0) = 0

n T(n) 1

n

1 s

+

− +

= ∑

=

P.K.

S筆 (n-S)筆

(21)

Strassen's Matrix Multiplication Algorithm

‹

矩陣乘法問題 (Matrix Multiplication Problem):

„

給定兩個方陣A, B,其Size均為n×n,其中 n=2 n=2

kk

。如果n不是2的冪次 方,則可以增加額外的列與行 增加額外的列與行,但是補上的元素都是零 零:

{

若矩陣是扁的,則可以在該矩陣下方補上數 列的0,使之成為方陣 列

{

若矩陣是窄的,則可以在該矩陣右方補上數 行的0,使之成為方陣 行

‹

欲求C = A × B,傳統的矩陣乘法:

c

11

= a

11

×b

11

+a

12

×b

21

c

12

= a

11

×b

12

+a

12

×b

22

c

21

= a

21

×b

11

+a

22

×b

21

c

22

= a

21

×b

12

+a

22

×b

22

(22)

‹

將矩陣乘法問題放大來看:

C

11

=

A11

×B

11

+

AA1212

× ×

BB2121

C

12

=

AA1111

× ×

BB1212

+

AA1212

× ×

BB2222

C

21

=

AA2121

× ×

BB1111

+

AA2222

× ×

BB2121

C

22

=

AA2121

× ×

BB1212

+

AA2222

× ×

BB2222

‹

遞迴方程式為: T(n) = 8T(n/2) +cn

2

‹

由支配理論可以得知該遞迴方程式最後可以得到 θ θ (n (n

33

) )

C

ij

, A

ij

, B

ij

皆為子矩陣 子矩陣,即可

用 遞迴切割的方式來將此矩 遞迴切割

陣切割成數個小矩陣。

(23)

‹

該演算法的時間複雜度為

O(nO(n33))

,乘法運算比加法運算要來得多。

„

前例的乘法有8個,加法有4個。

‹

然而,就系統執行的角度來說,乘法運算的複雜度遠超過加法運算,

因此該演算法在實際執行的速度會更慢。

(24)

‹

在1969年, Strassen 發 表了一個時間複雜度 較三次方演算法為佳 (time complexity is

better than cubic)的演 算法。

‹

Strassen的方法需要 7 7

次乘法和 次乘法和 18 18 次的加 次的加 / / 減 減

法 法

(25)

‹

遞迴方程式為: T(n) = 7T(n/2) +cn

2

‹

由支配理論可以得知該遞迴方程式最後可以得到θ(n

lg7

)

(26)

‹

在下列兩種情況,我們應免使用 Divide-and- conquer:

1) 一個大小為n的個體被分成兩個或更多個大小為接近n 的個體.

2) 一個大小為n的個體被分成n個大小為n/c的個體,其中 c為常數.

▓ 何時不能使用 Divide-and-Conquer

(27)

‹

有時,某些問題隨輸入範例的大小成指數成長是 無法避免的。雖然此時Divide-and-conquer無法獲 致良好的執行效率,但仍可採用。

„

河內塔問題每呼叫一次就需搬動圓盤一次,當圓盤的個 數 n 是64時,總共需要搬動圓盤 2

64

-1次,因此演算法 的複雜度等級 (order) 是 O(2

n

)

{

即: 河內塔問題的圓盤搬動次序是與 n 成 指數關係 指數關係

„

但是經過証明上述河內塔問題的演算法,已經是給定該

問題的限制下最佳的演算法則了。

參考文獻

相關文件

針對上述的第一類型(職災勞工)而言,一方面由於工廠、工具及工作站的建立都

在第一章我們已瞭解一元一次方程式的意義與解法,而在本章當中,我們將介紹

招式一:堅持拒絕法  招式五:友誼勸服法 招式二:告知理由法  招式六:轉移話題法

In x 2 we describe a top-down construction approach for which prototype charge- qubit devices have been successfully fabricated (Dzurak et al. Array sites are de­ ned by

並藉由適當工具與資訊,去描述、模擬、解釋與 預測各種現象,發揮數學思維方式的特長,做出

if left_sum&gt;=right_sum and left_sum&gt;=cross_sum return (left_low,left_high,left_sum). else if right_sum&gt;=left_sum and right_sum&gt;=cross_sum

證明比較鬆的upper bound或lower bound來慢慢 接近tight

Strassen’s method is not as numerically stable as 基本法..