亚洲在线久爱草,狠狠天天香蕉网,天天搞日日干久草,伊人亚洲日本欧美

為了賬號安全,請及時綁定郵箱和手機立即綁定
已解決430363個問題,去搜搜看,總會有你想問的

什么是尾遞歸?

什么是尾遞歸?

楊魅力 2019-05-28 17:30:32
什么是尾遞歸?在開始學習lisp時,我遇到了尾遞歸這個術語。這究竟是什么意思?
查看完整描述

4 回答

?
胡子哥哥

TA貢獻1825條經驗 獲得超6個贊

考慮一個添加前N個整數的簡單函數。(例如sum(5) = 1 + 2 + 3 + 4 + 5 = 15)。

這是一個使用遞歸的簡單JavaScript實現:

function recsum(x) {
    if (x===1) {
        return x;
    } else {
        return x + recsum(x-1);
    }}

如果你打電話recsum(5),這就是JavaScript解釋器會評估的內容:

recsum(5)5 + recsum(4)5 + (4 + recsum(3))5 + (4 + (3 + recsum(2)))5 + (4 + (3 + (2 + recsum(1))))5 + (4 + (3 + (2 + 1)))15

請注意每個遞歸調用必須在JavaScript解釋器開始實際執行計算總和之前完成。

這是同一函數的尾遞歸版本:

function tailrecsum(x, running_total=0) {
    if (x===0) {
        return running_total;
    } else {
        return tailrecsum(x-1, running_total+x);
    }}

這是您調用時將發生的事件序列tailrecsum(5)tailrecsum(5, 0)由于默認的第二個參數,這將是有效的)。

tailrecsum(5, 0)tailrecsum(4, 5)tailrecsum(3, 9)tailrecsum(2, 12)tailrecsum(1, 14)tailrecsum(0, 15)15

在尾遞歸的情況下,每次遞歸調用的評估running_total都會更新。

注意:原始答案使用了Python中的示例。這些已經改為JavaScript,因為現代JavaScript解釋器支持尾調用優化,但Python解釋器不支持。


查看完整回答
反對 回復 2019-05-28
?
嚕嚕噠

TA貢獻1784條經驗 獲得超7個贊

重要的一點是尾遞歸基本上等于循環。這不僅僅是編譯器優化的問題,而是表達性的基本事實。這有兩種方式:你可以采取任何形式的循環

while(E) { S }; return Q

where EQ是表達式,S是一系列語句,并將其轉換為尾遞歸函數

f() = if E then { S; return f() } else { return Q }

當然,E,S,和Q必須定義來計算對一些變量的一些有趣的價值。例如,循環函數

sum(n) {
  int i = 1, k = 0;
  while( i <= n ) {
    k += i;
    ++i;
  }
  return k;}

相當于尾遞歸函數

sum_aux(n,i,k) {
  if( i <= n ) {
    return sum_aux(n,i+1,k+i);
  } else {
    return k;
  }}sum(n) {
  return sum_aux(n,1,0);}

(這種帶有參數較少的函數的尾遞歸函數的“包裝”是一種常見的功能習慣。)


查看完整回答
反對 回復 2019-05-28
  • 4 回答
  • 0 關注
  • 837 瀏覽

添加回答

舉報

0/150
提交
取消
微信客服

購課補貼
聯系客服咨詢優惠詳情

幫助反饋 APP下載

慕課網APP
您的移動學習伙伴

公眾號

掃描二維碼
關注慕課網微信公眾號