3 3 1 遞迴計算

2021-06-25 21:37:45 字數 1251 閱讀 2754

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 ...