每天學一點 Kotlin -- 函數(shù):尾遞歸函數(shù)

----《第一季Kotlin崛起:次世代Android開發(fā) 》學習筆記

總目錄:每天學一點 Kotlin ---- 目錄
上一篇:每天學一點 Kotlin -- 函數(shù):字面量
下一篇:每天學一點 Kotlin -- 函數(shù):標準庫函數(shù)

1. 尾遞歸函數(shù)

1.1 遞歸函數(shù):當特定的目標沒有完成時,函數(shù)一直在自己調(diào)用自己。

1.2 但是遞歸也有弊端琼稻,就是在完成最后一次遞歸前會占用大量的資源和內(nèi)存焚挠。所以遞歸用的較少。而且能用遞歸實現(xiàn)的功能蔬充,用循環(huán)肯定也能實現(xiàn)亭罪。

1.3 如果一個遞歸函數(shù)的調(diào)用可以簡化到使用一個特殊函數(shù)作為最后一次操作弧蝇,且調(diào)用的結(jié)果是一個返回值歧沪,那么系統(tǒng)就不會保持上一次操作的內(nèi)存堆棧歹撒。因此就不需要其他臨時變量來維持進一步操作,直接返回這個特殊函數(shù)調(diào)用的值即可诊胞。這種技術(shù)被稱為尾遞歸暖夭。運用尾遞歸可以寫出高效的遞歸算法,從而避免堆棧溢出錯誤 ---- 尾遞歸是對遞歸的優(yōu)化撵孤。

1.4 要在 Kotlin 中使用一個尾遞歸函數(shù)鳞尔,可以用 tailrec 關(guān)鍵字定義函數(shù)。如此早直,編譯器便可以確信每一次遞歸使用這個函數(shù)作為最后一次操作寥假。

1.5 舉個栗子1:

fun main() {
    println(fact(5))
    println(fact2(5))
}
fun fact(k: Int): Int {
    println("k = " + k)
    if (k == 1) {
        return 1
    } else {
        var re = k * fact(k - 1)
        println("re = " + re)
        return re
    }
}

fun fact2(k: Int): Int {
    fun tailFact2(m: Int, n: Int): Int {
        println("m = " + m + ", n = " + n)
        if (m == 1) {
            return n
        } else {
            var re = tailFact2(m - 1, m + n)
            println("re = " + re)
            return re
        }
    }

    return tailFact2(k, 1)
}

打印結(jié)果:

普通的遞歸:
k = 5
k = 4
k = 3
k = 2
k = 1
re = 2
re = 6
re = 24
re = 120
120
使用尾遞歸的遞歸: 
m = 5, n = 1
m = 4, n = 6
m = 3, n = 10
m = 2, n = 13
m = 1, n = 15
re = 15
re = 15
re = 15
re = 15
15

可以看出,兩個函數(shù)計算的結(jié)果是一樣的霞扬,區(qū)別在于:
---- 普通的遞歸中糕韧,參數(shù)全部被保存下來,知道最后一層調(diào)用中計算得到結(jié)果后喻圃,再依次倒退和參數(shù)相加得到最終的結(jié)果
---- 在尾遞歸中萤彩,在 var re = tailFact2(m - 1, m + n) 這一行代碼中,每次向下調(diào)用自身時都已經(jīng)計算出結(jié)果了斧拍,直接把本次的結(jié)果向下計算雀扶,不需要保存之前的入?yún)?shù)了。

1.6 舉個栗子2:

fun main(args: Array<String>){
    println("普通的遞歸:start: " + System.currentTimeMillis())
    println("普通的遞歸:result = " + fibo(40))
    println("普通的遞歸:end: " + System.currentTimeMillis())

    println("使用尾遞歸的遞歸: start: " + System.currentTimeMillis())
    println("使用尾遞歸的遞歸:result = " + fibo2(40))
    println("使用尾遞歸的遞歸: end: " + System.currentTimeMillis())
}

// 之前的遞歸
fun fibo(startNum: Int): Int = when(startNum){
    0 -> 1
    1 -> 1
    else -> fibo(startNum - 1) + fibo(startNum - 2)
}

// 使用尾遞歸
fun fibo2(startNum: Int): Int{
   tailrec fun fiboTail(index: Int, ant: Int, act: Int): Int =
           when(index){
               0 -> ant
               else -> fiboTail(index - 1, act, ant + act)
           }

    return fiboTail(startNum, 1, 1)
}

打印結(jié)果:

普通的遞歸:start: 1634804071403
普通的遞歸:result = 165580141
普通的遞歸:end: 1634804071740
使用尾遞歸的遞歸: start: 1634804071740
使用尾遞歸的遞歸:result = 165580141
使用尾遞歸的遞歸: end: 1634804071740

可以看出肆汹,尾遞歸相比較與普通的遞歸愚墓,優(yōu)化效果還是很明顯的。

相關(guān)代碼:https://gitee.com/fzq.com/test-demo
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末昂勉,一起剝皮案震驚了整個濱河市浪册,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌岗照,老刑警劉巖村象,帶你破解...
    沈念sama閱讀 216,496評論 6 501
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異攒至,居然都是意外死亡厚者,警方通過查閱死者的電腦和手機,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,407評論 3 392
  • 文/潘曉璐 我一進店門迫吐,熙熙樓的掌柜王于貴愁眉苦臉地迎上來库菲,“玉大人,你說我怎么就攤上這事渠抹◎迹” “怎么了闪萄?”我有些...
    開封第一講書人閱讀 162,632評論 0 353
  • 文/不壞的土叔 我叫張陵,是天一觀的道長奇颠。 經(jīng)常有香客問我败去,道長,這世上最難降的妖魔是什么烈拒? 我笑而不...
    開封第一講書人閱讀 58,180評論 1 292
  • 正文 為了忘掉前任圆裕,我火速辦了婚禮,結(jié)果婚禮上荆几,老公的妹妹穿的比我還像新娘吓妆。我一直安慰自己,他們只是感情好吨铸,可當我...
    茶點故事閱讀 67,198評論 6 388
  • 文/花漫 我一把揭開白布行拢。 她就那樣靜靜地躺著,像睡著了一般诞吱。 火紅的嫁衣襯著肌膚如雪舟奠。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 51,165評論 1 299
  • 那天房维,我揣著相機與錄音沼瘫,去河邊找鬼。 笑死咙俩,一個胖子當著我的面吹牛耿戚,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播阿趁,決...
    沈念sama閱讀 40,052評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼膜蛔,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了歌焦?” 一聲冷哼從身側(cè)響起飞几,我...
    開封第一講書人閱讀 38,910評論 0 274
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎独撇,沒想到半個月后,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體躁锁,經(jīng)...
    沈念sama閱讀 45,324評論 1 310
  • 正文 獨居荒郊野嶺守林人離奇死亡纷铣,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,542評論 2 332
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了战转。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片搜立。...
    茶點故事閱讀 39,711評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖槐秧,靈堂內(nèi)的尸體忽然破棺而出啄踊,到底是詐尸還是另有隱情忧设,我是刑警寧澤,帶...
    沈念sama閱讀 35,424評論 5 343
  • 正文 年R本政府宣布颠通,位于F島的核電站址晕,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏顿锰。R本人自食惡果不足惜谨垃,卻給世界環(huán)境...
    茶點故事閱讀 41,017評論 3 326
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望硼控。 院中可真熱鬧刘陶,春花似錦、人聲如沸牢撼。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,668評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽熏版。三九已至牡直,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間纳决,已是汗流浹背碰逸。 一陣腳步聲響...
    開封第一講書人閱讀 32,823評論 1 269
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留阔加,地道東北人饵史。 一個月前我還...
    沈念sama閱讀 47,722評論 2 368
  • 正文 我出身青樓,卻偏偏與公主長得像胜榔,于是被迫代替她去往敵國和親胳喷。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 44,611評論 2 353

推薦閱讀更多精彩內(nèi)容