算法解析(三)遞歸

遞歸的基本概念網(wǎng)上一大堆斋陪,這里說(shuō)一下個(gè)人認(rèn)為重要的點(diǎn)。

(3.1)基本條件和遞歸條件

編寫遞歸函數(shù)時(shí)置吓,必須告訴它何時(shí)停止遞歸无虚。正因?yàn)槿绱耍總€(gè)遞歸函數(shù)都有兩部分:基線 條件(base case)遞歸條件(recursive case)衍锚。遞歸條件指的是函數(shù)調(diào)用自己友题,而基線條件則 指的是函數(shù)不再調(diào)用自己,從而避免形成無(wú)限循環(huán)戴质。

(3.2)棧

這里提一下一個(gè)概念:調(diào)用棧(call stack)

假設(shè)你去野外燒烤度宦,并為此創(chuàng)建了一個(gè)待辦事項(xiàng)清單——一疊 便條。

之前討論數(shù)組和鏈表時(shí)告匠,也有一個(gè)待辦事項(xiàng)清單戈抄。你可將待辦事 項(xiàng)添加到該清單的任何地方,還可刪除任何一個(gè)待辦事項(xiàng)后专。一疊便條要簡(jiǎn) 單得多:插入的待辦事項(xiàng)放在清單的最前面;讀取待辦事項(xiàng)時(shí)划鸽,你只讀取 最上面的那個(gè),并將其刪除戚哎。因此這個(gè)待辦事項(xiàng)清單只有兩種操作:壓入(插入)彈出(刪除并讀取)裸诽。

壓入和彈出.png

下面來(lái)看看如何使用這個(gè)待辦事項(xiàng)清單。


彈出.png

這種數(shù)據(jù)結(jié)構(gòu)稱為建瘫。棧是一種簡(jiǎn)單的數(shù)據(jù)結(jié)構(gòu)崭捍,剛才我們一直在使用它,卻沒(méi)有意識(shí)到!

(3.2.1)調(diào)用棧

計(jì)算機(jī)內(nèi)部使用的棧 我們稱為 調(diào)用棧啰脚。通過(guò)一個(gè)簡(jiǎn)單的函數(shù)了解一下殷蛇;

def greet(name):
        print "hello, " + name + "!" greet2(name)
        print "getting ready to say bye..." 
        bye()

這個(gè)函數(shù)問(wèn)候用戶实夹,再調(diào)用另外兩個(gè)函數(shù)。這兩個(gè)函數(shù)的代碼如下:

def greet2(name):
        print "how are you, " + name + "?"
def bye():
        print "ok bye!"

下面詳細(xì)介紹調(diào)用函數(shù)時(shí)發(fā)生的情況粒梦。
假設(shè)你調(diào)用greet("maggie")亮航,計(jì)算機(jī)將首先為該函數(shù)調(diào)用分配一塊內(nèi)存。


開(kāi)辟內(nèi)存.png

我們來(lái)使用這些內(nèi)存匀们。變量name被設(shè)置為maggie缴淋,這需要存儲(chǔ)到內(nèi)存中。

使用內(nèi)存.png

每當(dāng)你調(diào)用函數(shù)時(shí)泄朴,計(jì)算機(jī)都像這樣將函數(shù)調(diào)用涉及的所有變量的值存儲(chǔ)到內(nèi)存中重抖。接下來(lái), 你打印hello, maggie!祖灰,再調(diào)用greet2("maggie")钟沛。同樣,計(jì)算機(jī)也為這個(gè)函數(shù)調(diào)用分配一 塊內(nèi)存局扶。
函數(shù)內(nèi)調(diào)用函數(shù).png

計(jì)算機(jī)使用一個(gè)棧來(lái)表示這些內(nèi)存塊恨统,其中第二個(gè)內(nèi)存塊位于第一個(gè)內(nèi)存塊上面

然后從函數(shù)調(diào)用返回。此時(shí)三妈,棧頂?shù)膬?nèi)存塊被彈出畜埋。


函數(shù)返回.png
現(xiàn)在,棧頂?shù)膬?nèi)存塊是函數(shù)greet的畴蒲,這意味著你返回到了函數(shù)greet悠鞍。當(dāng)你調(diào)用函數(shù)greet2 時(shí),函數(shù)greet只執(zhí)行了一部分
如果在當(dāng)前函數(shù)里調(diào)用另外一個(gè)函數(shù)饿凛,當(dāng)前函數(shù)暫停并處于未完成狀態(tài)狞玛,該函數(shù)的所有變量都還在內(nèi)存中。

你回到函數(shù) greet涧窒,并從離開(kāi)的地方開(kāi)始接著往下執(zhí)行,再調(diào)用 函數(shù)bye锭亏。


函數(shù)再次調(diào)用.png

函數(shù)bye 返回之后:


函數(shù)bye返回.png

現(xiàn)在你又回到了函數(shù)greet纠吴。由于沒(méi)有別的事情要做,你就從函數(shù)greet返回慧瘤。這個(gè)棧用于存儲(chǔ)多個(gè)函數(shù)的變量戴已,被稱為調(diào)用棧。

(3.3)遞歸調(diào)用棧

遞歸函數(shù)也使用調(diào)用棧! 下面舉例說(shuō)明:聲明一個(gè)階乘函數(shù)锅减,詳細(xì)分析一下 調(diào)用棧

函數(shù):

def fact(x):
    if x == 1: 
        return 1
    else:
        return x * fact(x-1)

當(dāng)首次調(diào)用為fact(3)的時(shí)候糖儡,調(diào)用棧的變化如下:


遞歸調(diào)用棧.jpg
函數(shù)調(diào)用棧開(kāi)始返回.png
注意,每個(gè)fact調(diào)用都有自己的x變量怔匣。在一個(gè)函數(shù)調(diào)用中不能訪問(wèn)另一個(gè)的x變量握联。

使用棧雖然很方便,但是也要付出代價(jià):存儲(chǔ)詳盡的信息可能占用大量的內(nèi)存。每個(gè)函數(shù)調(diào) 用都要占用一定的內(nèi)存金闽,如果棧很高纯露,就意味著計(jì)算機(jī)存儲(chǔ)了大量函數(shù)調(diào)用的信息。在這種情況 下代芜,你有兩種選擇埠褪。

  • 重新編寫代碼,轉(zhuǎn)而使用循環(huán)挤庇。
  • 使用尾遞歸钞速。

小結(jié):

  • 遞歸指的是調(diào)用自己的函數(shù)。
  • 每個(gè)遞歸函數(shù)都有兩個(gè)條件:基線條件和遞歸條件嫡秕。
  • 棧有兩種操作:壓入和彈出渴语。
  • 所有函數(shù)調(diào)用都進(jìn)入調(diào)用棧。
  • 調(diào)用椞云校可能很長(zhǎng)遵班,這將占用大量的內(nèi)存。
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末潮改,一起剝皮案震驚了整個(gè)濱河市狭郑,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌汇在,老刑警劉巖翰萨,帶你破解...
    沈念sama閱讀 219,539評(píng)論 6 508
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異糕殉,居然都是意外死亡亩鬼,警方通過(guò)查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,594評(píng)論 3 396
  • 文/潘曉璐 我一進(jìn)店門阿蝶,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)雳锋,“玉大人,你說(shuō)我怎么就攤上這事羡洁$韫” “怎么了?”我有些...
    開(kāi)封第一講書人閱讀 165,871評(píng)論 0 356
  • 文/不壞的土叔 我叫張陵筑煮,是天一觀的道長(zhǎng)辛蚊。 經(jīng)常有香客問(wèn)我,道長(zhǎng)真仲,這世上最難降的妖魔是什么袋马? 我笑而不...
    開(kāi)封第一講書人閱讀 58,963評(píng)論 1 295
  • 正文 為了忘掉前任,我火速辦了婚禮秸应,結(jié)果婚禮上虑凛,老公的妹妹穿的比我還像新娘碑宴。我一直安慰自己,他們只是感情好卧檐,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,984評(píng)論 6 393
  • 文/花漫 我一把揭開(kāi)白布墓懂。 她就那樣靜靜地躺著,像睡著了一般霉囚。 火紅的嫁衣襯著肌膚如雪捕仔。 梳的紋絲不亂的頭發(fā)上,一...
    開(kāi)封第一講書人閱讀 51,763評(píng)論 1 307
  • 那天盈罐,我揣著相機(jī)與錄音榜跌,去河邊找鬼。 笑死盅粪,一個(gè)胖子當(dāng)著我的面吹牛钓葫,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播票顾,決...
    沈念sama閱讀 40,468評(píng)論 3 420
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼础浮,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼!你這毒婦竟也來(lái)了奠骄?” 一聲冷哼從身側(cè)響起豆同,我...
    開(kāi)封第一講書人閱讀 39,357評(píng)論 0 276
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎含鳞,沒(méi)想到半個(gè)月后影锈,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,850評(píng)論 1 317
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡蝉绷,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 38,002評(píng)論 3 338
  • 正文 我和宋清朗相戀三年鸭廷,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片熔吗。...
    茶點(diǎn)故事閱讀 40,144評(píng)論 1 351
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡辆床,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出桅狠,到底是詐尸還是另有隱情佛吓,我是刑警寧澤,帶...
    沈念sama閱讀 35,823評(píng)論 5 346
  • 正文 年R本政府宣布垂攘,位于F島的核電站,受9級(jí)特大地震影響淤刃,放射性物質(zhì)發(fā)生泄漏晒他。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,483評(píng)論 3 331
  • 文/蒙蒙 一逸贾、第九天 我趴在偏房一處隱蔽的房頂上張望陨仅。 院中可真熱鬧津滞,春花似錦、人聲如沸灼伤。這莊子的主人今日做“春日...
    開(kāi)封第一講書人閱讀 32,026評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)狐赡。三九已至撞鹉,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間颖侄,已是汗流浹背鸟雏。 一陣腳步聲響...
    開(kāi)封第一講書人閱讀 33,150評(píng)論 1 272
  • 我被黑心中介騙來(lái)泰國(guó)打工, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留览祖,地道東北人孝鹊。 一個(gè)月前我還...
    沈念sama閱讀 48,415評(píng)論 3 373
  • 正文 我出身青樓,卻偏偏與公主長(zhǎng)得像展蒂,于是被迫代替她去往敵國(guó)和親又活。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,092評(píng)論 2 355

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

  • 遞歸是很多算法都使用的一種編程方法锰悼。聽(tīng)說(shuō)遞歸是一種十分優(yōu)雅的問(wèn)題解決辦法柳骄,可是對(duì)于初涉遞歸的我,還沒(méi)有形成這種獨(dú)特...
    愛(ài)吃西瓜的番茄醬閱讀 1,181評(píng)論 0 5
  • 計(jì)算機(jī)科學(xué)的新學(xué)生通常難以理解遞歸程序設(shè)計(jì)的概念。遞歸思想之所以困難隘世,原因在于它非常像是循環(huán)推理(circular...
    啟明_b56f閱讀 7,367評(píng)論 0 20
  • 感謝社區(qū)中各位的大力支持可柿,譯者再次奉上一點(diǎn)點(diǎn)福利:阿里云產(chǎn)品券,享受所有官網(wǎng)優(yōu)惠丙者,并抽取幸運(yùn)大獎(jiǎng):點(diǎn)擊這里領(lǐng)取 在...
    HetfieldJoe閱讀 1,812評(píng)論 0 14
  • 一复斥、遞歸定義 如果函數(shù)中包含了對(duì)其自身的調(diào)用,該函數(shù)就是遞歸的械媒; 遞歸(Recursion)目锭,在數(shù)學(xué)與計(jì)算機(jī)科學(xué)中...
    惑也閱讀 10,853評(píng)論 0 4
  • Swift1> Swift和OC的區(qū)別1.1> Swift沒(méi)有地址/指針的概念1.2> 泛型1.3> 類型嚴(yán)謹(jǐn) 對(duì)...
    cosWriter閱讀 11,105評(píng)論 1 32