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

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

遞歸調用的特殊性在於自己調用自己,給人一種迷茫感,如果是遞歸調用“一次”,那還相對好理解,比如求階乘的遞歸算法,

  1. int F(int n)
  2. {
  3. if(n==0)//遞歸邊界
  4.             return 1;
  5. return n*F(n-1);//遞歸公式
  6. }

一層一層調用,知道遞歸結束條件成立,再一層一層返回;但如果像二叉樹是遞歸調用“兩次”,似乎理解起來就不是很容易了。

  1. void preorder(bintree t){
  2. if(t){
  3. printf("%c ",t->data);
  4. preorder(t->lchild);
  5. preorder(t->rchild);
  6. }
  7. }

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

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

首先,我們記上面這個函數爲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”。

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

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章