遞歸
遞歸程序
在支持自調(diào)用的編程語(yǔ)言中,遞歸可以通過(guò)簡(jiǎn)單的函數(shù)調(diào)用來(lái)完成,如計(jì)算階乘的程序在數(shù)學(xué)上可以定義為:
這一程序在Scheme語(yǔ)言中可以寫(xiě)作:
(define (factorialn)(if (= n0)1(* n(factorial(- n1)))))
不動(dòng)點(diǎn)組合子
即使一個(gè)編程語(yǔ)言不支持自調(diào)用,如果在這語(yǔ)言中函數(shù)是第一類(lèi)對(duì)象(即可以在運(yùn)行期創(chuàng)建并作為變量處理),遞歸可以通過(guò)不動(dòng)點(diǎn)組合子(英語(yǔ):Fixed-point combinator)來(lái)產(chǎn)生。以下Scheme程序沒(méi)有用到自調(diào)用,但是利用了一個(gè)叫做Z 算子(英語(yǔ):Z combinator)的不動(dòng)點(diǎn)組合子,因此同樣能達(dá)到遞歸的目的。
(define Z(lambda (f)((lambda (recur)(f(lambda arg(apply (recurrecur)arg))))(lambda (recur)(f(lambda arg(apply (recurrecur)arg)))))))(define fact(Z(lambda (f)(lambda (n)(if (<= n0)1(* n(f(- n1))))))))
這一程序思路是,既然在這里函數(shù)不能調(diào)用其自身,我們可以用 Z 組合子應(yīng)用(application)這個(gè)函數(shù)后得到的函數(shù)再應(yīng)用需計(jì)算的參數(shù)。
尾部遞歸
尾部遞歸是指遞歸函數(shù)在調(diào)用自身后直接傳回其值,而不對(duì)其再加運(yùn)算。尾部遞歸與循環(huán)是等價(jià)的,而且在一些語(yǔ)言(如Scheme中)可以被優(yōu)化為循環(huán)指令。 因此,在這些語(yǔ)言中尾部遞歸不會(huì)占用調(diào)用堆??臻g。以下Scheme程序同樣計(jì)算一個(gè)數(shù)字的階乘,但是使用尾部遞歸:
(define (factorialn)(define (iterproductcounter)(if (> countern)product(iter(* counterproduct)(+ counter1))))(iter11))
能夠解決的問(wèn)題
1、數(shù)據(jù)的定義是按遞歸定義的。如Fibonacci函數(shù)。
2、問(wèn)題解法按遞歸算法實(shí)現(xiàn)。如Hanoi問(wèn)題。
3、數(shù)據(jù)的結(jié)構(gòu)形式是按遞歸定義的。如二叉樹(shù)、廣義表等。
遞歸數(shù)據(jù)
數(shù)據(jù)類(lèi)型可以通過(guò)遞歸來(lái)進(jìn)行定義,比如一個(gè)簡(jiǎn)單的遞歸定義為自然數(shù)的定義:“一個(gè)自然數(shù)或等于0,或等于另一個(gè)自然數(shù)加上1”。Haskell中可以定義鏈表為:
dataListOfStrings=EmptyList|ConsStringListOfStrings
這一定義相當(dāng)于宣告“一個(gè)鏈表或是空串列,或是一個(gè)鏈表之前加上一個(gè)字符串”??梢钥闯鏊墟湵矶伎梢酝ㄟ^(guò)這一遞歸定義來(lái)達(dá)到。
免責(zé)聲明:以上內(nèi)容版權(quán)歸原作者所有,如有侵犯您的原創(chuàng)版權(quán)請(qǐng)告知,我們將盡快刪除相關(guān)內(nèi)容。感謝每一位辛勤著寫(xiě)的作者,感謝每一位的分享。
相關(guān)資料
展開(kāi)- 有價(jià)值
- 一般般
- 沒(méi)價(jià)值
{{item.userName}} 舉報(bào)
{{item.time}} {{item.replyListShow ? '收起' : '展開(kāi)'}}評(píng)論 {{curReplyId == item.id ? '取消回復(fù)' : '回復(fù)'}}
{{_reply.userName}} 舉報(bào)
{{_reply.time}}