遞迴與尾遞迴

2022-07-14 08:06:09 字數 2228 閱讀 7103

在最近做專案的時候碰到某個統計查詢比較慢,比較影響效率,經過排查發現是這個程式使用了遞迴呼叫,我遍歷的是組織架構,

當這個層級很深時這個程式就會越慢,

這是我寫的統計某個組織的下屬組織總數

1/**

2* 疊加父級下子級的數量(遞迴呼叫)

3* @param pd 封裝的pagedata用來接受引數(可以理解成map)

4* @param res 初始為0

5* @return

6* @throws exception7*/

8public integer listsubtype(pagedata pd,int

res) throws exception

15return res;//

返回統計結果

16 }

這個是我本地的資料庫,資料量並不多

普通遞迴執行花費時間

讓函式在末尾被呼叫,好辦, 於是稍微改了下**(其實就是把this改為了return)

1/**

2* 疊加父級下子級的數量(遞迴呼叫)

3* @param pd 封裝的pagedata用來接受引數(可以理解成map)

4* @param res 初始為0

5* @return

6* @throws exception7*/

8public integer listsubtype(pagedata pd,int

res) throws exception

15return res;//

返回統計結果

16 }

尾遞迴執行花費時間

差距是不是很明顯,當然我取得只是測試中某乙個值,兩者之間花費時間我也各測試了好幾次,我取的是大概中間值

其實到了這一步也差不多完成了優化,可我對這其中的原理還是一知半解,普通遞迴好理解,但尾遞迴呢?於是繼續研究

1

//例一

2function f(x)67

//例二

8function f(x)

上面的的兩個都不屬於尾遞迴(不對,應該是不屬於尾呼叫),因為在呼叫自身後它們還需要進行操作,

尾呼叫:尾呼叫是指乙個函式裡的最後乙個動作是乙個函式呼叫的情形,即這個呼叫的返回值直接被當前函式返回的情形。這種情形下稱該呼叫位置稱為「尾位置」

尾遞迴:若乙個函式在尾位置呼叫自身,則稱這種情況為尾遞迴。尾遞迴是遞迴的一種特殊情形

這樣也算是初步理解了尾遞迴與尾呼叫的概念了

那麼為什麼普通遞迴與尾遞迴的查詢效率會差這麼多呢

查詢資料得:

函式呼叫會在記憶體形成乙個"呼叫記錄",又稱"呼叫幀"(call frame),儲存呼叫位置和內部變數等資訊。如果在函式a的內部呼叫函式b,那麼在a的呼叫記錄上方,還會形成乙個b的呼叫記錄。等到b執行結束,將結果返回到a,b的呼叫記錄才會消失。如果函式b內部還呼叫函式c,那就還有乙個c的呼叫記錄棧,以此類推。所有的呼叫記錄,就形成乙個"呼叫棧"

(call stack)

尾呼叫由於是函式的最後一步操作,所以不需要保留外層函式的呼叫記錄,因為呼叫位置、內部變數等資訊都不會再用到了,只要直接用內層函式的呼叫記錄,取代外層函式的呼叫記錄就可以了

自己理解的如下

這是用普通遞迴求1到n的和

1

int fn( int

n )2

如果輸入的是3,那麼大家理解的就是2+3=5,裡面的真實計算為fn(0)+fn(1)+fn(2)+fn(3)

這是用尾遞迴求1到n的和

1

int fn( int n,int

res)

2

如果輸入的是3,那麼就是2+3=5等價於fn(2)+fn(3),因為2和3已經計算好的可以直接拿過來用,而不需要再次計算

不用尾遞迴,函式的堆疊耗用難以估量,需要儲存很多中間函式的堆疊。比如f(n, sum) = f(n-1) + value(n) + sum; 會儲存n個函式呼叫堆疊,而使用尾遞迴f(n, sum) = f(n-1, sum+value(n)); 這樣則只保留後乙個函式堆疊即可

以上我寫的優化查詢的確實有問題,但遞迴與尾遞迴的解釋還是可以參考的

遞迴與尾遞迴

1 遞迴 關於遞迴的概念,我們都不陌生。簡單的來說遞迴就是乙個函式直接或間接地呼叫自身,是為直接或間接遞迴。一般來說,遞迴需要有邊界條件 遞迴前進段和遞迴返回段。當邊界條件不滿足時,遞迴前進 當邊界條件滿足時,遞迴返回。用遞迴需要注意以下兩點 1 遞迴就是在過程或函式裡呼叫自身。2 在使用遞迴策略時...

遞迴與尾遞迴

1 遞迴 簡單的來說遞迴就是乙個函式直接或間接地呼叫自身,是為直接或間接遞迴。一般來說,遞迴需要有邊界條件 遞迴前進段和遞迴返回段。當邊界條件不滿足時,遞迴前進 當邊界條件滿足時,遞迴返回。用遞迴需要注意以下兩點 1 遞迴就是在過程或函式裡呼叫自身。2 在使用遞迴策略時,必須有乙個明確的遞迴結束條件...

遞迴與尾遞迴

前言 今天上網看帖子的時候,看到關於尾遞迴的應用 大腦中感覺這個詞好像在 見過,但是又想不起來具體是怎麼回事。如是乎,在網上搜了一下,頓時豁然開朗,知道尾遞迴是怎麼回事了。下面就遞迴與尾遞迴進行總結,以方便日後在工作中使用。1 遞迴 關於遞迴的概念,我們都不陌生。簡單的來說遞迴就是乙個函式直接或間接...