Java 程式設計(一)  第 六章 方法與套件引用  上一頁    下一頁

 

6-4 遞迴函數

  • 6-4-1 遞迴函數的流程

  • 6-4-2 範例研討:累乘遞迴函數

  • 6-4-3 自我挑戰:曼波舞表演系統

6-4-1 遞迴函數的流程

主程式呼叫函數後,系統轉移到函數上執行,但函數可能再呼叫其他函數,這是非常普遍的現象。如果執行某一函數當中,它會再呼叫自己的函數,則稱之為『遞迴函數』(Recursive function)。許多程式設計師喜歡利用遞迴函數來減低程式的設計量,但遞迴函數會佔用許多記憶體空間,並不是非常理想的程式設計手法。

所謂呼叫函數,即是將函數的程式碼倒入記憶體空間,再去執行他;如果呼叫許多函數,則導入了許多程式碼進入系統。當程式碼進入系統之後,隨之被啟動執行,與原來程式碼沒有任何關係,執行完畢之後,記憶體程式碼隨之被刪除,但磁碟空間內的程式碼還是保留著。如果某一函數一直呼叫自己,則是不斷的導入與自己相同的程式碼進入主記憶體,前後導入的程式碼之間並沒有任何關連,如圖 6-5 所示。

6-10 遞迴函數的運作程序

讀者也許會納悶,如果某一函數會呼叫自己的函數,當然下一次呼叫的函數,還是會再呼叫自己,則將會無窮盡的延伸下去。為了能讓遞迴函數能有停止的時間,函數內必需加入判斷敘述,條件成立再呼叫自己函數,否則必須轉回。因此,遞迴函數有某種固定的格式,範例如下:

範例:level(n) = 1 * 2 *3 * 4 *, …, *n

說明:total = level(5) 的運作程序

static int level(int k) {

if (k <=1)

return 1;

else

return (k* level(k-1));

}

假設主程式呼叫上述遞迴函數,並給予引數 5 為例(total = level(5)),其運作程序說明如表 6-1 所示。第一次呼叫時 k=5,條件判斷不成立,則執行 return k * level(k-1),當呼叫執行 level(4) 時,同樣再呼叫自己,依此類推,一直到 k=1。當 k=1 時,條件成立,則返回 1,接著 level(2) 返回得到 2level(3) 返回得到 6...,最後 level(5) 返回得到 120

6-1 遞迴函數 level(5) 執行步驟

次數

level(k)

K

K <=1

執行動作

返回

1

level(5)

5

no

return (5 * level(4))

5 * 24 = 120

2

level(4)

4

no

return (4 * level(3))

4 * 6 = 24

3

level(3)

3

no

return ( 3 * level(2)))

3 * 2 = 6

4

level(2)

2

no

return (2 * level(1))

2*1 = 2

5

level(1)

1

yes

return 1

1

6-4-2 範例研討:累乘遞迴程式

A)程式功能:Ex6_4.java

請利用呼叫遞迴函數來編寫累乘程式,程式允需輸入一個整數 n,計算並輸出 total = 1 * 2 * 3 * 4 *, …, nn!);亦需顯示每次遞迴呼叫的執行內容,期望操作介面如下:

B)製作技巧研討:

利用任何迴圈敘述句(forwhile)都很容易製作累乘程式,但系統要求利用遞迴函數,只好照辦。另外,系統要求列印每次呼叫遞迴函數的結果,吾人必須在函數內加入列印的功能。

C)程式範例:

C)程式範例:

01

02

03

04

05

06

07

08

09

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

/Ex6_4.java

 

import java.util.*;

public class Ex6_4 {

    public static void main(String args[]) {

        Scanner keyin = new Scanner(System.in);

        int total, num;

        System.out.printf("請輸入一個整數 =>");

        num = keyin.nextInt();

        total = level(num);

        System.out.printf("1*2*3*, ..., %d = %d\n", num, total);

    }

    /* 遞迴函數開始 */

    static int level(int k) {

        int sum;

        if (k <= 1)

            return 1;

        else {

            sum = k * level(k-1);

            System.out.printf("%d * level(%d-1) = %d\n", k, k, sum);

            return sum;

        }

    } /* 遞迴函數結束 */

}

(D) 程式重點說明:

(1) 14~23 static int level(int k) {…}。遞迴函數主體。

(2) 16~17 if( k<=1 ) retrun 1;。表示遞迴函數結束。

(3) 18~22 else { sum = k * level(k-1); …}。函數呼叫與自己名稱相同的函數,但引數減少(k-1)。

(4) 20 System.out.printf(…)。印出每次呼叫函數的執行結果。

6-4-3 自我挑戰:曼波舞步表演系統

A)程式功能:PM6-2.java

曼波舞步的步法是進一步再退一步、進兩步再退兩步、進三步再退三步,依此類推。前進多少步則相對應後退多少步,當然不會直線進退,可選擇任何路徑進行;又此可見,連續越多步法越困難。請製作一套曼波舞步表演系統,並可隨觀眾喜好選擇表演級數,期望操作系統介面如下:

G:\Examples\chap6>java PM6_2

== 曼波舞步表演系統 ==

請輸入表演級數 =>4

1 階舞步 =>1 1

2 階舞步 =>1 2 2 1

3 階舞步 =>1 2 3 3 2 1

4 階舞步 =>1 2 3 4 4 3 2 1

謝謝參觀

以第 2 階舞步為例,前進兩步(1, 2),之後緊接著後退兩步(2, 1)。

B)製作技巧提示。

舞步中可區分『前進』與『後退』兩種步法,前進多少步則後退幾步;吾人可分別利用兩個遞迴函數來達成,前進遞迴函數(front_dance())可連續印出 123...k;後退遞迴函數(back_dance)則 k... 321。另外,由觀眾選擇希望觀賞的級數(num),表演出 n = 1, 2, .., k 階層的舞步。虛擬碼提示如下:

虛擬碼提示如下:

觀眾選擇觀賞級數(n);

for (int k=1; k<=n; k++) {

顯示表演階層(k);

呼叫前進遞迴函數(front_dance(k));

呼叫後退遞迴函數(back_dance(k));

}

static void fornt_dance(int k) {     // 前進遞迴函數宣告

  if (k <= 1)

       System.out.printf("1 ");

  else {

       front_dance(k-1);

       System.out.printf("%d ", k);

   }

}

static void back_dance(int k) {      // 後退遞迴函數宣告

   if (k <= 1)

        System.out.printf("1 ");

   else {

        System.out.printf("%d ", k);

        back_dance(k-1);

   }

}

翻轉工作室:粘添壽

 

Java 程式設計(一) 含程式邏輯

 

 

翻轉電子書系列: