徹底理解遞迴,從遞迴的本質說起!

2021-10-01 03:33:03 字數 2819 閱讀 2398

遍歷二叉樹,是學習樹這種資料結構首先要理解的一種基本操作。比較簡單地方式就是用遞迴去遍歷,鑑於遞迴這種呼叫方法有一定的特殊性,今天還是想來講講怎麼去理解遞迴遍歷。本文針對想理解遞迴的過程的朋友,因為本人在學到這一部分的時候也糾結了很久,其實只要理解了過程,那以後寫遞迴的**再也不用「心虛」了,因為那個過程是可**的,可證明的。

遞迴呼叫的特殊性在於自己呼叫自己,給人一種迷茫感,如果是遞迴呼叫「一次」,那還相對好理解,比如求階乘的遞迴演算法,

int

f(int n)

一層一層呼叫,知道遞迴結束條件成立,再一層一層返回;但如果像二叉樹是遞迴呼叫「兩次」,似乎理解起來就不是很容易了。

void

preorder

(bintree t)

}

對於一顆如下的二叉樹,它的前序遍歷順序該怎麼理解呢?我們今天來好好理一遍它的過程。

可以把遞迴看成是自己呼叫另乙個和自己功能一樣,但是函式名不同的函式來理解,或許看得更清楚明白,下面我們來看看這個前序遍歷的過程是怎樣的。

首先,我們記上面這個函式為f1,表示外層的函式,內層函式表示下一層的函式,也就是第二層的f2,依次類推。

那從f1依次呼叫直到f3,注意這個時候都是在左子樹就是l的呼叫,所以依次列印出「a b d 」,這都沒什麼問題,就是普通函式呼叫。f3呼叫f4的時候,記得我們層函式的最前面是遞迴的退出條件,也就是空子樹就返回,由於d的左子樹是空,所以到這裡f4會返回到f3,即返回到l之後,r之前。

接在,在f3層,從r開始繼續呼叫f4,即開始訪問d的右子樹,此時列印出「f」,然後呼叫f4的左子樹,也就是呼叫f5函式,當然是空,所以返回到f4,再呼叫f4的右子樹,也是空,所以也是返回到f4,此時f4這一層已經全部呼叫完成,所以繼續向上返回到f3,記得我們之前是怎麼下來的嗎,就是從f3的右子樹開始訪問,所以f3層函式也已經呼叫完成,繼續往上返回到f2。

繼續呼叫f2的右子樹,也就是呼叫f3函式,此時列印出「e」,接著再訪問e的左右子樹,都是空,所以返回到f2,f2層函式已經全部呼叫完成。返回到f1,也就是a的左子樹部分全部訪問完成,此時開始訪問a的右子樹,列印出「c」,再推下去就是依次列印「g」和「h」。至此,整顆二叉樹節點前序遍歷完成,順序就是「a b d f e c g h」。

二叉樹是一種遞迴定義的資料結構,所以用遞迴來寫它的相關演算法是順理成章的,只是有時候覺得需要稍微理解一下這個過程,這個就是我的理解方法。

遍歷二叉樹,是學習樹這種資料結構首先要理解的一種基本操作。比較簡單地方式就是用遞迴去遍歷,鑑於遞迴這種呼叫方法有一定的特殊性,今天還是想來講講怎麼去理解遞迴遍歷。本文針對想理解遞迴的過程的朋友,因為本人在學到這一部分的時候也糾結了很久,其實只要理解了過程,那以後寫遞迴的**再也不用「心虛」了,因為那個過程是可**的,可證明的。

遞迴呼叫的特殊性在於自己呼叫自己,給人一種迷茫感,如果是遞迴呼叫「一次」,那還相對好理解,比如求階乘的遞迴演算法,

int

f(int n)

一層一層呼叫,知道遞迴結束條件成立,再一層一層返回;但如果像二叉樹是遞迴呼叫「兩次」,似乎理解起來就不是很容易了。

void

preorder

(bintree t)

}

對於一顆如下的二叉樹,它的前序遍歷順序該怎麼理解呢?我們今天來好好理一遍它的過程。

可以把遞迴看成是自己呼叫另乙個和自己功能一樣,但是函式名不同的函式來理解,或許看得更清楚明白,下面我們來看看這個前序遍歷的過程是怎樣的。

首先,我們記上面這個函式為f1,表示外層的函式,內層函式表示下一層的函式,也就是第二層的f2,依次類推。

那從f1依次呼叫直到f3,注意這個時候都是在左子樹就是l的呼叫,所以依次列印出「a b d 」,這都沒什麼問題,就是普通函式呼叫。f3呼叫f4的時候,記得我們層函式的最前面是遞迴的退出條件,也就是空子樹就返回,由於d的左子樹是空,所以到這裡f4會返回到f3,即返回到l之後,r之前。

接在,在f3層,從r開始繼續呼叫f4,即開始訪問d的右子樹,此時列印出「f」,然後呼叫f4的左子樹,也就是呼叫f5函式,當然是空,所以返回到f4,再呼叫f4的右子樹,也是空,所以也是返回到f4,此時f4這一層已經全部呼叫完成,所以繼續向上返回到f3,記得我們之前是怎麼下來的嗎,就是從f3的右子樹開始訪問,所以f3層函式也已經呼叫完成,繼續往上返回到f2。

繼續呼叫f2的右子樹,也就是呼叫f3函式,此時列印出「e」,接著再訪問e的左右子樹,都是空,所以返回到f2,f2層函式已經全部呼叫完成。返回到f1,也就是a的左子樹部分全部訪問完成,此時開始訪問a的右子樹,列印出「c」,再推下去就是依次列印「g」和「h」。至此,整顆二叉樹節點前序遍歷完成,順序就是「a b d f e c g h」。

二叉樹是一種遞迴定義的資料結構,所以用遞迴來寫它的相關演算法是順理成章的,只是有時候覺得需要稍微理解一下這個過程,這個就是我的理解方法。

遞迴的本質

遞迴簡單的來說遞迴就是乙個函式直接或間接地呼叫自身,是為直接或間接遞迴。一般來說,遞迴需要有邊界條件 遞迴前進段和遞迴返回段 其實就是進棧出棧的操作 當邊界條件不滿足時,遞迴前進 當邊界條件滿足時,遞迴返回。用遞迴需要注意以下兩點 1 遞迴就是在過程或函式裡呼叫自身。2 在使用遞迴策略時,必須有乙個...

遞迴 從青蛙跳台階說起

迭代與遞迴從本質上講,都是一種迴圈過程。迭代主要是在每一步中更新變數值來達到迴圈的目的,而遞迴則是在函式中呼叫自己來實現迴圈。迭代更直觀,我們一眼能夠看出程式執行過程,而遞迴則使得程式更加簡潔緊湊。對於迭代,我們給定乙個迴圈指標 迴圈範圍以及需要更新的變數就可以進行迴圈了,例如 for i in r...

從約瑟夫問題的遞迴實現的問題說起

在解決約瑟夫問題時,我比較推薦使用遞迴,因為遞迴實現的演算法 更短,邏輯也更清晰,然而很多人有乙個疑問,那就是他們知道遞迴層數是有極限的,這就意味著當需要很大層數的遞迴時,遞迴演算法是不可行的,會導致段錯誤。對於這個問題我有三個回答 第一,只要你使用的是計算機而不是你的大腦,你就不要指望什麼是無限制...