Scala Learning(3): Tail Recursion定義

關於尾遞歸 ,使用Scala的兩個例子展示尾遞歸的定義和簡單實現。

例子比較

求最大公約數的函數

def gcd(a: Int, b: Int): Int =
  if (b == 0) a else gcd(b, a % b)

計算的展開是尾遞歸的,

gcd(14, 21)
-> if (21 == 0) 14 else gcd(21, 14 % 21)
-> if (false) 14 else gcd(21, 14 % 21)
-> gcd(21, 14 % 21)
-> gcd(21, 14)
-> if (14 == 0) 21 else gcd(14, 21 % 14)
-> gcd(14, 7)
-> gcd(7, 0)
-> if (0 == 0) 7 else gcd(0, 7 % 0)
-> 7

求階乘的函數

def factorial(n: Int): Int =
  if (n == 0) 1 else n * factorial(n - 1)

計算的展開是非尾遞歸的,

factorial(4)
-> if (4 == 0) 1 else 4 * factorial(4 - 1)
-> 4 * factorial(3)
-> 4 * (3 * factorial(2))
-> 4 * (3 * (2 * factorial(1)))
-> 4 * (3 * (2 * (1 * factorial(0)))
-> 4 * (3 * (2 * (1 * 1)))
-> 120

尾遞歸定義

一個簡單精煉的定義:

If a function calls itself as its last action, the function`s stack frame can be reused. This is called tail recursion.

gcd函數在else分支後面調用的是自己,而factorial函數在else分支裏,調用自己之後還乘以了n,所以不是尾遞歸。

改寫

factorial函數裏,寫一個函數,接收n以及累計的乘積值,即可變成尾遞歸。

def factorial(n: Int): Int = {
  def tailIter(product: Int, n: Int): Int = {
    if (n == 0) product
    else tailIter(product*n, n-1)
  }
  tailIter(1, n)
}

全文完 :)

發佈了158 篇原創文章 · 獲贊 25 · 訪問量 94萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章