GO語言————6.6 遞迴函式
6.6 遞迴函式
當一個函式在其函式體內呼叫自身,則稱之為遞迴。最經典的例子便是計算斐波那契數列,即前兩個數為1,從第三個數開始每個數均為前兩個數之和。
數列如下所示:
1, 1, 2, 3, 5, 8, 13, 21, 34, 55, 89, 144, 233, 377, 610, 987, 1597, 2584, 4181, 6765, 10946, …
下面的程式可用於生成該數列(示例 6.13 fibonacci.go):
package main
import "fmt"
func main() {
result := 0
for i := 0; i <= 10; i++ {
result = fibonacci(i)
fmt.Printf("fibonacci(%d) is: %d\n", i, result)
}
}
func fibonacci(n int) (res int) {
if n <= 1 {
res = 1
} else {
res = fibonacci(n-1) + fibonacci(n-2)
}
return
}
輸出:
fibonacci(0) is: 1
fibonacci(1) is: 1
fibonacci(2) is: 2
fibonacci(3) is: 3
fibonacci(4) is: 5
fibonacci(5) is: 8
fibonacci(6) is: 13
fibonacci(7) is: 21
fibonacci(8) is: 34
fibonacci(9) is: 55
fibonacci(10) is: 89
許多問題都可以使用優雅的遞迴來解決,比如說著名的快速排序演算法。
在使用遞迴函式時經常會遇到的一個重要問題就是棧溢位:一般出現在大量的遞迴呼叫導致的程式棧記憶體分配耗盡。這個問題可以通過一個名為懶惰求值的技術解決,在 Go 語言中,我們可以使用管道(channel)和 goroutine(詳見第 14.8 節)來實現。練習 14.12 也會通過這個方案來優化斐波那契數列的生成問題。
Go 語言中也可以使用相互呼叫的遞迴函式:多個函式之間相互呼叫形成閉環。因為 Go 語言編譯器的特殊性,這些函式的宣告順序可以是任意的。下面這個簡單的例子展示了函式 odd 和 even 之間的相互呼叫(示例 6.14 mut_recurs.go):
package main
import (
"fmt"
)
func main() {
fmt.Printf("%d is even: is %t\n", 16, even(16)) // 16 is even: is true
fmt.Printf("%d is odd: is %t\n", 17, odd(17))
// 17 is odd: is true
fmt.Printf("%d is odd: is %t\n", 18, odd(18))
// 18 is odd: is false
}
func even(nr int) bool {
if nr == 0 {
return true
}
return odd(RevSign(nr) - 1)
}
func odd(nr int) bool {
if nr == 0 {
return false
}
return even(RevSign(nr) - 1)
}
func RevSign(nr int) int {
if nr < 0 {
return -nr
}
return nr
}
練習題
練習 6.4
重寫本節中生成斐波那契數列的程式並返回兩個命名返回值(詳見第 6.2 節),即數列中的位置和對應的值,例如 5 與 4,89 與 10。
練習 6.5
使用遞迴函式從 10 列印到 1。
練習 6.6
實現一個輸出前 30 個整數的階乘的程式。
n! 的階乘定義為:n! = n * (n-1)!, 0! = 1
,因此它非常適合使用遞迴函式來實現。
然後,使用命名返回值來實現這個程式的第二個版本。
特別注意的是,使用 int 型別最多隻能計算到 12 的階乘,因為一般情況下 int 型別的大小為 32 位,繼續計算會導致溢位錯誤。那麼,如何才能解決這個問題呢?
最好的解決方案就是使用 big 包(詳見第 9.4 節)。
相關文章
- C#語言函式遞迴C#函式遞迴
- Go 語言函式Go函式
- GO語言————6.1 函式Go函式
- Go 語言 -make函式Go函式
- Go語言入門教程系列——函式、迴圈與分支Go函式
- go語言學習-函式Go函式
- 遞迴函式遞迴函式
- c語言_遞迴C語言遞迴
- 函式表示式–遞迴函式遞迴
- 函式 -- 就要學習 Go 語言函式Go
- GO語言————6.5 內建函式Go函式
- 函式的遞迴函式遞迴
- 函式之遞迴函式遞迴
- Python 函式進階-遞迴函式Python函式遞迴
- 函式遞迴與生成式函式遞迴
- 5.go語言函式提綱Go函式
- 1.5.6 python遞迴函式Python遞迴函式
- 13.0、python遞迴函式Python遞迴函式
- 遞迴函式的理解遞迴函式
- 第 8 節:函式-匿名函式、遞迴函式函式遞迴
- c語言遞迴函式實現求最大公約數(Euclid演算法)C語言遞迴函式演算法
- JS函式表示式——函式遞迴、閉包JS函式遞迴
- 【Go】Go語言學習筆記-2-函式Go筆記函式
- 小白學習Golang(六)Go語言函式Golang函式
- go語言入門之-函式和方法Go函式
- GO語言入門 - (六)函式和方法Go函式
- 清華尹成帶你實戰GO案例(26)Go 遞迴函式Go遞迴函式
- 【C語言】函式的概念和函式的呼叫(引數傳遞)C語言函式
- day 17 – 1 遞迴函式遞迴函式
- 遞迴函式-樹形列表遞迴函式
- 遞迴函式例項大全遞迴函式
- 函數語言程式設計之尾呼叫和尾遞迴函數程式設計遞迴
- GO語言————6.7 將函式作為引數Go函式
- 【Go語言學習】匿名函式與閉包Go函式
- go 遞迴Go遞迴
- 初學 PHP 函式的遞迴PHP函式遞迴
- [20180531]函式呼叫與遞迴.txt函式遞迴
- bilibiliclass10and11_函式遞迴函式遞迴