在最近做專案的時候碰到某個統計查詢比較慢,比較影響效率,經過排查發現是這個程式使用了遞迴呼叫,我遍歷的是組織架構,
當這個層級很深時這個程式就會越慢,
這是我寫的統計某個組織的下屬組織總數
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如果輸入的是3,那麼大家理解的就是2+3=5,裡面的真實計算為fn(0)+fn(1)+fn(2)+fn(3)int fn( int
n )2
這是用尾遞迴求1到n的和
1如果輸入的是3,那麼就是2+3=5等價於fn(2)+fn(3),因為2和3已經計算好的可以直接拿過來用,而不需要再次計算int fn( int n,int
res)
2
不用尾遞迴,函式的堆疊耗用難以估量,需要儲存很多中間函式的堆疊。比如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 遞迴 關於遞迴的概念,我們都不陌生。簡單的來說遞迴就是乙個函式直接或間接...