Scala高階之路 尾遞迴優化

2021-09-08 14:09:56 字數 2394 閱讀 4046

scala高階之路-尾遞迴優化

遞迴呼叫有時候能被轉換成迴圈,這樣能節約棧空間。在函式式程式設計中,這是很重要的,我們通常會使用遞迴方法來遍歷集合。而不是所有的遞迴都能被優化。遞迴之所有能被優化是在指在函式的最後一行為遞迴呼叫(即尾遞迴),並且這個遞迴呼叫沒有其它元素參與。

一.什麼情況能導致棧的溢位

1>.迴圈呼叫

答:迴圈呼叫並不會導致棧的溢位,因為迴圈是乙個壓棧和彈棧的過程。

2>.遞迴呼叫

答:遞迴呼叫會導致棧的溢位。因為遞迴呼叫一直在壓棧,而之前的棧並不會釋放資源,這樣隨著壓棧的堆積,棧空間溢位那是遲早的事兒。

3>.尾遞迴

答:可以進行優化,將遞迴轉換成迴圈實現,避免棧的溢位。

二.尾遞迴優化案例展示

1>尾遞迴不能有其它引數參與

我們先以下案例:

1/*2

@author :yinzhengjie

3blog:

4email:[email protected]*/

6package

cn.org.yinzhengjie.function78

object tailrecursion else16}

17 def main(args: array[string]): unit =

20 }

以上**測試結果如下:

2>.尾遞迴優化

我們將上面的**稍微進行改動,就可以輕鬆實現尾遞迴優化啦。具體**如下:

1/*2

@author :yinzhengjie

3blog:

4email:[email protected]*/

6package

cn.org.yinzhengjie.function78

object tailrecursion else16}

17 def main(args: array[string]): unit =")20}

21 }

測試結果如下:

三.如果編寫尾遞迴函式

所謂的尾遞迴就是最後一步如果是遞迴操作本身(即沒有和其它引數參與),此時它就是乙個尾遞迴函式,它就變成迴圈了,因此不會出現棧溢位的情況。能實現尾遞迴的原理就是當然的棧並不需要從下乙個棧中拿資料才能釋放。也就是說,當前的棧呼叫下乙個棧時不依賴下乙個棧返回資料才能結束,因此當它呼叫下乙個棧時,也就可以讓當前的棧執行彈棧操作,當下乙個棧執行完畢時,也不需要下下個棧返回資料,因此,下乙個棧也可以實現彈棧操作,綜上所述,尾遞迴的就和咱們寫的死迴圈是乙個原理啦,就是實現壓棧和彈棧的過程,因此始終不會棧溢位的情況喲!

我們再舉乙個尾遞迴的例子如下:

1/*2

@author :yinzhengjie

3blog:

4email:[email protected]*/

6package

cn.org.yinzhengjie.function78

object tailrecursion

14 def main(args: array[string]): unit =

17 }

以上程式我執行了5分鐘,依舊沒有出現棧溢位的情況,

當然如果是你講上面的尾遞迴函式的兩行**調換一下,當然依舊還是遞迴函式,但最後一行不是遞迴函式本身了,因此不是尾遞迴函式,很顯然會出現棧記憶體溢位。

scala 尾遞迴優化

乙個函式直接或間接的呼叫它自己本身,就是遞迴。它通常把乙個大型複雜的問題層層轉化為乙個與原問題相似的規模較小的問題來求解,遞迴策略只需少量的 就可以執行多次重複的計算。一般來說,遞迴需要有邊界條件 遞迴前進段和遞迴返回段。當邊界條件不滿足時,遞迴前進 當邊界條件滿足時,遞迴返回。以遞迴方式實現階乘函...

高階函式與尾遞迴優化

高階函式特點 1.函式接收的引數是乙個函式 2.函式的return值中包含函式 滿足以上任一條件就稱這個函式為高階函式。高階函式例子 某個函式的return值可以是任何函式,包括自己 ef test1 print from test1 def test2 print from test2 retur...

尾遞迴優化

尾遞迴就是遞迴語句在函式最後執行,且無需對返回值進行進一步操作。編譯器會對這種遞迴進行優化,在進入深層遞迴時候,不是在遞迴棧進行入棧操作,而是直接覆蓋棧頂。線性遞迴與尾遞迴區別如下 線性遞迴 1 2 3 4 5 longrescuvie longn 尾遞迴 1 2 3 4 5 6 7 8 9 10 ...