18
資資資資 1 遞遞 Recursive 資資資資 資資資

遞迴 Recursive

Embed Size (px)

DESCRIPTION

遞迴 Recursive. 授課老師:蕭志明. 遞迴( Recursive ). 一個副程式或函數重複的呼叫自己本身,稱為遞迴 (Recursive) 。 利用遞迴解決問題,既經濟又方便。 可用遞回來解決的問題,那它也一定可轉成利用非遞迴的方式解決之。 撰寫遞迴時,千萬小心,一定要有一個結束點,否則後果嚴重。 遞迴在執行時,會藉助堆疊將呼叫本身函數的下一個敘述位址儲存起來,待執行完結束點後,再將堆疊的資料一一的彈出來處理。. 遞迴 設計步驟. 發展從一個或多個較小實例的解中得到較大實例的解之方式。 決定分割為較小實例的終止條件。 決定終止條件時的解。. 階乘. - PowerPoint PPT Presentation

Citation preview

資料結構

1

遞迴Recursive

授課老師:蕭志明

資料結構

2

遞迴( Recursive )

1. 一個副程式或函數重複的呼叫自己本身,稱為遞迴 (Recursive) 。

2. 利用遞迴解決問題,既經濟又方便。3. 可用遞回來解決的問題,那它也一定可

轉成利用非遞迴的方式解決之。4. 撰寫遞迴時,千萬小心,一定要有一個

結束點,否則後果嚴重。5. 遞迴在執行時,會藉助堆疊將呼叫本身

函數的下一個敘述位址儲存起來,待執行完結束點後,再將堆疊的資料一一的彈出來處理。

資料結構

3

遞迴設計步驟

1. 發展從一個或多個較小實例的解中得到較大實例的解之方式。

2. 決定分割為較小實例的終止條件。

3. 決定終止條件時的解。

資料結構

4

階乘

求 n! ,一般可能用的規則:n! = n * (n-1)!;

利用迴圈: ans = 1;for (i = 2; i <= n; i++) ans = ans * i;

利用遞迴: int fact(int n)

{

int x, y;

if (n == 0) // boundary condition

return(1);

x = n-1;

y = fact(x);

return(n*y);

} /* end fact */

資料結構

5

遞迴呼叫流程圖

fact(3)

y=fact(2)

fact(2)

y=fact(1)

fact(1)

y=fact(0)

fact(0)

Return(1)

fact(4)

y=fact(3)

n=3n=2 n=1 n=0

Fact(0)=1

Fact(1)=1

Fact(2)=2

Fact(3)=6

Fact(4)=24

int fact(int n) { int x, y; if (n == 0) // boundary condition return(1); x = n-1; y = fact(x); return(n*y);

} /* end fact */

n=4

資料結構

6

遞迴呼叫流程圖

練習: fact(5) 的呼叫過程,遞迴呼叫流程圖為何。

int fact(int n) { int x, y; if (n == 0) // boundary condition return(1); x = n-1; y = fact(x); return(n*y);

} /* end fact */

n=5

資料結構

7

遞迴推疊圖(The recursive stack)

呼叫過程 :

f2

f3

f4

f0

f1

資料結構

8

n x y

(i)printf(“%d”, fact(3))

The stack at various times during execution during execution.(An asterisk indicates an uninitialized value.)

資料結構

9

資料結構

10

費氏數列

費氏數列 (Fibonacci number) :f(0) = 0;* f(1) = 1;f(2) = f(1) + f(0);f(3) = f(2) + f(1);:f(n) = f(n-1) + f(n-2);

利用遞迴範例: int fib(int n)

{

int x, y;

if (n <= 1)

return(n);

x = fib(n-1);

y = fib(n-2);

return(x+y);

} /* end fib */

資料結構

11

遞迴呼叫流程圖fib(4)

x=fib(3)

y=fib(2)

fib(4)=3

fib(3)

x=fib(2)

y=fib(1)

n=3

fib(3)=2

fact(2)

x=fib(1)

y=fact(0)

fib(1)

Return(1)

n=2

n=1

fib(1)=1

fib(2)=1

fib(0)

Return(0)

n=0

fib(0)=0

fib(1)

Return(1)

n=1

fib(1)=1

fact(2)

x=fib(1)

y=fact(0)

fib(1)

Return(1)

n=2

n=1

fib(1)=1

fib(2)=1

fib(0)

Return(0)

n=0

fib(0)=0

int fib(int n) {

int x, y; if (n <= 1) return(n); x = fib(n-1); y = fib(n-2); return(x+y);

} /* end fib */

n=4

資料結構

12

遞迴推疊圖(The recursive stack)

呼叫過程 :

f1f2

f2f3

f4

f1 f0

f0f1

資料結構

13

遞迴推疊圖

練習: fib(5) 的呼叫過程,請用樹狀結構來表示。

int fib(int n) {

int x, y; if (n <= 1) return(n); x = fib(n-1); y = fib(n-2); return(x+y);

} /* end fib */

n=5

資料結構

14

遞迴推疊圖

呼叫過程 : f5

f1f2

f2f3

f4 f3

f2 f1

f0f1 f0 f1

f0f1

資料結構

15

資料結構

16

資料結構

17

何時不要使用遞迴?

遞迴雖然可以使用少數幾行的敘述就可以解決一些複雜的問題,但有些問題會使用更多的執行時間。

以費氏數列為例: 遞迴之複雜度為 O(2n) ,而迴圈只要 O(n) 。

約需時 2n/2

資料結構

18

結論

1.以階乘為例:無論使用遞迴或迴圈,複雜度階為 O(n) 。 但遞迴需要較大的記憶體空間。

2.結論: 執行過程像一棵灌木,但重複動作太多

的,如:費氏數列,不適用遞迴。 然而,若重複動作很少時,如: N 個皇后,則適用遞迴。

執行過程不像灌木,而是一直線的前進與後退,如:階乘,亦不適用遞迴。

以迴圈會使程式困難設計時,可考慮用遞迴。