6-4 遞迴函數 6-4-1 遞迴函數的流程 主程式呼叫函數後,系統轉移到函數上執行,但函數可能再呼叫其他函數,這是非常普遍的現象。如果執行某一函數當中,它會再呼叫自己的函數,則稱之為『遞迴函數』(Recursive function)。許多程式設計師喜歡利用遞迴函數來減低程式的設計量,但遞迴函數會佔用許多記憶體空間,並不是非常理想的程式設計手法。 所謂呼叫函數,即是將函數的程式碼倒入記憶體空間,再去執行他;如果呼叫許多函數,則導入了許多程式碼進入系統。當程式碼進入系統之後,隨之被啟動執行,與原來程式碼沒有任何關係,執行完畢之後,記憶體程式碼隨之被刪除,但磁碟空間內的程式碼還是保留著。如果某一函數一直呼叫自己,則是不斷的導入與自己相同的程式碼進入主記憶體,前後導入的程式碼之間並沒有任何關連,如圖 6-5 所示。 圖6-10 遞迴函數的運作程序 讀者也許會納悶,如果某一函數會呼叫自己的函數,當然下一次呼叫的函數,還是會再呼叫自己,則將會無窮盡的延伸下去。為了能讓遞迴函數能有停止的時間,函數內必需加入判斷敘述,條件成立再呼叫自己函數,否則必須轉回。因此,遞迴函數有某種固定的格式,範例如下:
假設主程式呼叫上述遞迴函數,並給予引數 5 為例(total = level(5)),其運作程序說明如表 6-1 所示。第一次呼叫時 k=5,條件判斷不成立,則執行 return k * level(k-1),當呼叫執行 level(4) 時,同樣再呼叫自己,依此類推,一直到 k=1。當 k=1 時,條件成立,則返回 1,接著 level(2) 返回得到 2、level(3) 返回得到 6...,最後 level(5) 返回得到 120。 表 6-1 遞迴函數 level(5) 執行步驟
6-4-2 範例研討:累乘遞迴程式 (A)程式功能:Ex6_4.java 請利用呼叫遞迴函數來編寫累乘程式,程式允需輸入一個整數 n,計算並輸出 total = 1 * 2 * 3 * 4 *, …, n(n!);亦需顯示每次遞迴呼叫的執行內容,期望操作介面如下: (B)製作技巧研討: 利用任何迴圈敘述句(for、while)都很容易製作累乘程式,但系統要求利用遞迴函數,只好照辦。另外,系統要求列印每次呼叫遞迴函數的結果,吾人必須在函數內加入列印的功能。 (C)程式範例: (C)程式範例:
(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 曼波舞步的步法是進一步再退一步、進兩步再退兩步、進三步再退三步,依此類推。前進多少步則相對應後退多少步,當然不會直線進退,可選擇任何路徑進行;又此可見,連續越多步法越困難。請製作一套曼波舞步表演系統,並可隨觀眾喜好選擇表演級數,期望操作系統介面如下:
以第 2 階舞步為例,前進兩步(1, 2),之後緊接著後退兩步(2, 1)。 (B)製作技巧提示。 舞步中可區分『前進』與『後退』兩種步法,前進多少步則後退幾步;吾人可分別利用兩個遞迴函數來達成,前進遞迴函數(front_dance())可連續印出 1、2、3...等k;後退遞迴函數(back_dance)則 k...等 3、2、1。另外,由觀眾選擇希望觀賞的級數(num),表演出 n = 1, 2, .., k 階層的舞步。虛擬碼提示如下: 虛擬碼提示如下:
|
翻轉工作室:粘添壽
Java 程式設計(一) 含程式邏輯
翻轉電子書系列:
|