3.3.1 遞迴計算
遞迴函式最常見的示例是計算乙個數的階乘。如果你不熟悉,這裡有乙個簡單的定義:乙個非負數 n 的階乘,當 n 等於 1 或 0 時,等於1;對於更大的 n,等於 n-1 的階乘乘以 n。這個函式的實現,基本上有兩種方式。在 c# 中,可以使用 for 迴圈,數字在 2 到 n 之間進行迭代,用第次迭代的數乘以臨時變數:
int factorial(int n) {
intres = 1;
for(int i = 2; i <= n; i++)
res = res * i;
return res;
這是乙個正確的實現,但不容易看出函式所對應的數學定義。函式的第二種實現方式使用遞迴,在 c# 中定義方法,或在 f# 中定義函式,以遞迴方式呼叫自身。這兩個實現驚人的相似,可以在清單 3.12 中看到並列排放的兩個定義。
清單 3.12 階乘的遞迴實現,用c# 和 f#
c#f#
int factorial(int n) { [1]
if (n <= 1)
return 1; [2]
else
return n * factorial(n - 1); [3]
let rec factorial(n) = [1]
if (n <= 1) then
1 [2]
else
n * factorial(n - 1) [3]
遞迴函式或方法的宣告[1]。在 f# 中,必須顯式宣告函式是遞迴的,用 let rec 繫結,代替普通的 let。
模式匹配包含兩種情況。第一種情況,終止遞迴,並立即返回 1 [2];第二種情況,執行遞迴呼叫 factorial 函式或 factorial 方法。
c# 版本的**非常簡單;f# 版本也相當清晰,只是必須使用 rec 關鍵字,顯式宣告函式是遞迴的。這個關鍵字說明 let 繫結是遞迴的,這樣,就可以引用函式宣告內部值的名字(factorial)。
一般情況下,每個遞迴計算都應有至少兩個分支:乙個分支用於執行遞迴呼叫的計算,另乙個分支用於終止計算,在清單 3.12 中可以看到兩個分支。通常,遞迴計算執行幾次遞迴呼叫,直到終止條件出現(這裡,是計算 1 的階乘),返回某個常量的值,或使用非遞迴**計算結果。如果終止條件不正確,**可能永遠迴圈下去,或最終由於堆疊溢位異常而崩潰。
遞迴對於函式程式設計來說是絕對的核心,因此,函式語言已經開發出一些方法和優化機制,避免了即使深度遞迴呼叫,也不會出現堆疊溢位的問題。這些以及更高階的主題將在第十章討論。
33 遞迴計算累加和
一.問題 給定乙個數 n 用遞迴的手法求出從 1 到 n 的累加和。1.例項分析 假設傳入引數 n 5。方法一 高斯公式 1 int gauss sum int n 利用公式,一次即可算出答案,時間複雜度為 o 1 方法二 迴圈計算 1 int normal sum int n 6 7return ...
使用php遞迴計算目錄大小
統計乙個目錄大小,因為不知道目錄中子目錄的深度,所以for迴圈很難實現,但是用遞迴呼叫很容易實現,只要統計出乙個目錄中所有檔案的大小,那麼每一次呼叫就可以了,隨便建了個目錄,建立一些檔案,方法 如下 1 function dirsize dirname 9 if is dir dirname.ite...
Python 遞迴計算分數數列
c語言的課後習題 求數列 2 1,3 2,5 3,8 5,13 8,21 13,前50項的和 數列規律 第二項的分母是 前一項分子 第二項的分子是 前一項分子與分母的和 from fractions import fraction def fn x 計算每一項的值 time 1 fz 2 fm 1 ...