1 / 26

Chapter 3

Chapter 3. 遞迴. 3.1 何謂遞迴. 遞迴程式簡單的說即是「一程式呼叫自己本身( call itself)」, 在高階語言中, C、Pascal、Ada 及人工智慧語言 Lisp、Prolog 都提供了遞迴呼叫的功能,根據呼叫形式的不同,又分為: *. 3.1 何謂遞迴. 直接遞迴 若一副程式 P 直接呼叫自己本身,便稱之為直接遞迴。 間接遞迴 若一副程式 P 呼叫另一副程式 Q, 而副程式 Q 又呼叫副程式 P, 此種形式的遞迴關係便稱之為間接遞迴。 *. 3.1 何謂遞迴.

alika-tyler
Download Presentation

Chapter 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. Chapter 3 遞迴

  2. 3.1 何謂遞迴 • 遞迴程式簡單的說即是「一程式呼叫自己本身(call itself)」,在高階語言中,C、Pascal、Ada及人工智慧語言Lisp、Prolog都提供了遞迴呼叫的功能,根據呼叫形式的不同,又分為: *

  3. 3.1 何謂遞迴 • 直接遞迴若一副程式P直接呼叫自己本身,便稱之為直接遞迴。 • 間接遞迴若一副程式P呼叫另一副程式Q,而副程式Q又呼叫副程式P,此種形式的遞迴關係便稱之為間接遞迴。 *

  4. 3.1 何謂遞迴 • 在一般遞迴呼叫中,為滿足演算法的有限性(definite),所以必須有一結束遞迴呼叫的條件,此即「終止條件」(termination condition)。 *

  5. 3.2 一些遞迴的例子 費式數列(Fibonacci number) • 圖3-2-1中,將兩塊玻璃背對放著,設 *

  6. 3.2 一些遞迴的例子 • 當n=0時,表示光線方向不變,所以a0=1,而n>1時,可分成兩種情況 • 光線跳到對面層,再以an-1的方式反彈,如a3中的第3、4、5種方式。 • 光線跳到中間層,再以an-2的方式反彈,如a3中的第1、2種方式。 • 由上述說明,可得到一數學關係式 *

  7. 3.2 一些遞迴的例子 • 下面我們定義一數列Fn,其下一項值為前二項值之和,且初始條件為F0=0,F1=1 • 很顯然地,此數列滿足 • 這就是「費式數列」的數學定義式。 *

  8. 3.2 一些遞迴的例子 • 底下程式則是說明如何求第n項費式數列值的遞迴程式。  // 費氏級數,此項等於前兩項之和int recursion::fib(int n){ if (n<2) return n; else return (fib(n-1)+fib(n-2)); // 遞迴呼叫自已} *

  9. 3.2 一些遞迴的例子 • 從費式數列的定義中,可知欲求fib(6)時,必先呼叫fib(5)及fib(4),而在求fib(5)時,又要呼叫fib(4)及fib(3),所有呼叫次序如圖3-2-2。

  10. 3.2 一些遞迴的例子 漢諾塔(Hanoi Tower) • 一則有趣的故事傳說:在開天闢地之初,上帝將64個由大而小疊好的金盤放在一根金針上,命令一群教徒利用另兩根金針,把這些金盤搬到第三根金針上,且搬運過程中,必須遵守二條原則 (1)一次只能搬動一個盤子。 (2)小金盤必須在大金盤之上。 • 當他們完成這項工作的時候,也就是世界末日的來到。 *

  11. 3.2 一些遞迴的例子 • 想要解決這個複雜的問題,可先考慮兩個盤子的解答。 * 圖3-2-3 兩個金盤的漢諾塔

  12. 3.2 一些遞迴的例子 • 聰明的讀者可以發現,如果是搬n個盤子時,亦是同上圖,將n-1個盤子先移到B,再將第n個盤子移到C,最後將n-1個盤子移到C即可完成。 *

  13. 3.2 一些遞迴的例子 • 以下程式實作漢諾塔的遞迴程式。 // 漢諾塔void recursion::hanoi(int plates,char source,char target, char put){ if (plates>0) { // 將n-1個盤子先移到B hanoi(plates-1,source,put,target);

  14. 3.2 一些遞迴的例子   // 將第n個盤子移到C cout << "Move plate No." << plates << " from "<< source << " to " << target << endl; // 將n-1個盤子移到C hanoi(plates-1,put,target,source); }} *

  15. 3.3 解遞迴式 • 在上面的費式數列中,若想知道fib(n)的值究竟有多大,必須呼叫圖3-2-2各節點,所以一時無法推估它的大小,這是許多遞迴程式共同的特徵,為克服此項缺點,我們以費式數列為例子,引進解遞迴式的方法。 *

  16. 3.3 解遞迴式 • 考慮遞迴式如下:Fn=Fn-1+Fn-2 ,n>1因為n=1時,左式等於1,右式等於0,所以 • 步驟一 將上式修正成Fn=Fn-1+Fn-2+(n=1) • 步驟二 令G(Z)= FnZn所以G(Z)= FnZn= [Fn-1+ Fn-2 +(n=1)] Z n= FnZn + Fn-2Zn + (n=1)Z n= FnZn+1+ FnZn+2+Z= ZG(Z)+ Z2 G(Z)+Z *

  17. 3.3 解遞迴式 • 步驟三 設 • 因此 1-Z-Z2=1-(α+β)Z+αβZ2。 • 所以可得其中一組解 *

  18. 3.3 解遞迴式 • (1+√5)/2就是藝術上所稱的「黃金比(golden ratio)」,意含此種比例設計最令人愉快,最後可得   G(Z)=1/√5((1/(1-αZ))-(1/(1-βZ)))    =1/√5Σ(αn-βn)Zn  所以 Fn=1/√5(αn-βn) • 因此,若想知道fib(n)之值,即可把n代入上式,即可求出。 *

  19. 3.4 使用遞迴的優缺點 • 從圖3-2-2中看出,在計算fib(6)時,遞迴過程中呼叫次數如表3-4-1。 *

  20. 3.4 使用遞迴的優缺點 • 因此其效率極差,若我們把它改成非遞迴的程式,效率將可大大改進:  // 費氏級數,此項等於前兩項之和int unrecursion::fib(int n){ int i,prev=0,now=1,next; if (n<2) return n; else {

  21. 3.4 使用遞迴的優缺點 for (i=2;i<=n;i++) { next=prev+now; prev=now; now=next; } } return now;} *

  22. 3.4 使用遞迴的優缺點 • 再看看漢諾塔的效率問題,設Tn表示將n個盤子由一金針搬至另一金針所需的時間,由前面說明可看出,搬移m個盤子共需2Tn-1+1次移動,所以可得 *

  23. 3.4 使用遞迴的優缺點 • 我們發現它的時間複雜度(time complexity)呈指數成長,因此即使要搬完64個金盤,也需264次才能完成,縱然每一微秒搬動一次,也要50000世紀才能完成。 *

  24. 3.4 使用遞迴的優缺點 • 一般而言,使用遞迴會付出下列兩點代價: 較花時間,效率較差原因有二,第一,編譯器可能將遞迴程式編譯成效差的碼,在最差的情況下,一個遞迴性的程序效率只大約只有非遞迴性程序的一半。第二,我們的遞迴程式也許簡單但效率差,如費式級數就需要重複呼叫副程式多次。 *

  25. 3.4 使用遞迴的優缺點 需較多記憶空間因為每一次遞迴呼叫中,都要將原來的變數、參數等存起來,所以遞迴深度愈大所需的記憶體就愈大。 *

  26. 3.4 使用遞迴的優缺點 • 但遞迴程式,也具有下列二項優點: 效率分析簡單如上面漢諾塔的分析、簡易清晰。 設計自然、簡單下一節中,讀者可輕易觀察出對應遞迴程式的非遞迴程式,較遞迴程式複雜多了。 *

More Related