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

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

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

  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”。

二叉樹是一種遞迴定義的資料結構,所以用遞迴來寫它的相關演算法是順理成章的,只是有時候覺得需要稍微理解一下這個過程,這個就是我的理解方法。
---------------------
作者:allenchenhh133
來源:CSDN
地址:https://blog.csdn.net/allenchenhh133/article/details/80291252


相關文章