遞歸是一種重要的編程技術(shù)。該方法用于讓一個(gè)函數(shù)從其內(nèi)部調(diào)用其自身。一個(gè)示例就是計(jì)算階乘。0 的階乘被特別地定義為 1。 更大數(shù)的階乘是通過計(jì)算 1 * 2 * ...來求得的,每次增加 1,直至達(dá)到要計(jì)算其階乘的那個(gè)數(shù)。
下面的段落是用文字定義的計(jì)算階乘的一個(gè)函數(shù)。
“如果這個(gè)數(shù)小于零,則拒絕接收。如果不是一個(gè)整數(shù),則將其向下舍入為相鄰的整數(shù)。如果這個(gè)數(shù)為 0,則其階乘為 1。如果這個(gè)數(shù)大于 0,則將其與相鄰較小的數(shù)的階乘相乘?!?/P>
要計(jì)算任何大于 0 的數(shù)的階乘,至少需要計(jì)算一個(gè)其他數(shù)的階乘。用來實(shí)現(xiàn)這個(gè)功能的函數(shù)就是已經(jīng)位于其中的函數(shù);該函數(shù)在執(zhí)行當(dāng)前的這個(gè)數(shù)之前,必須調(diào)用它本身來計(jì)算相鄰的較小數(shù)的階乘。這就是一個(gè)遞歸示例。
遞歸和迭代(循環(huán))是密切相關(guān)的 — 能用遞歸處理的算法也都可以采用迭代,反之亦然。確定的算法通常可以用幾種方法實(shí)現(xiàn),您只需選擇最自然貼切的方法,或者您覺得用起來最輕松的一種即可。
顯然,這樣有可能會出現(xiàn)問題。可以很容易地創(chuàng)建一個(gè)遞歸函數(shù),但該函數(shù)不能得到一個(gè)確定的結(jié)果,并且不能達(dá)到一個(gè)終點(diǎn)。這樣的遞歸將導(dǎo)致計(jì)算機(jī)執(zhí)行一個(gè)“無限”循環(huán)。下面就是一個(gè)示例:在計(jì)算階乘的文字描述中遺漏了第一條規(guī)則(對負(fù)數(shù)的處理) ,并試圖計(jì)算任何負(fù)數(shù)的階乘。這將導(dǎo)致失敗,因?yàn)榘错樞蛴?jì)算 -24 的階乘時(shí),首先不得不計(jì)算 -25 的階乘;然而這樣又不得不計(jì)算 -26 的階乘;如此繼續(xù)。很明顯,這樣永遠(yuǎn)也不會到達(dá)一個(gè)終止點(diǎn)。
因此在設(shè)計(jì)遞歸函數(shù)時(shí)應(yīng)特別仔細(xì)。如果懷疑其中存在著無限遞歸的可能,則可以讓該函數(shù)記錄它調(diào)用自身的次數(shù)。如果該函數(shù)調(diào)用自身的次數(shù)太多,即使您已決定了它應(yīng)調(diào)用多少次,就自動(dòng)退出。
下面仍然是階乘函數(shù),這次是用 JScript 代碼編寫的。
// 計(jì)算階乘的函數(shù)。如果傳遞了
// 無效的數(shù)值(例如小于零),
// 將返回 -1,表明發(fā)生了錯(cuò)誤。若數(shù)值有效,
// 把數(shù)值轉(zhuǎn)換為最相近的整數(shù),并
// 返回階乘。
function factorial(aNumber) {
aNumber = Math.floor(aNumber); // 如果這個(gè)數(shù)不是一個(gè)整數(shù),則向下舍入。
if (aNumber < 0) { // 如果這個(gè)數(shù)小于 0,拒絕接收。
return -1;
}
if (aNumber == 0) { // 如果為 0,則其階乘為 1。
return 1;
}
else return (aNumber * factorial(aNumber - 1)); // 否則,遞歸直至完成。
更多信息請查看IT技術(shù)專欄