㈠ 選擇題:一個遞歸演算法必須包括()
一個遞歸演算法必須包括B、終止條件和遞歸部分。
遞歸演算法在計算機科學中是指一種通過重復將問題分解為同類的子問題而解決問題的方法。
遞歸式方法可以被用於解決很多的計算機科學問題,因此它是計算機科學中十分重要的一個概念。絕大多數編程語言支持函數的自調用,在這些語言中函數可以通過調用自身來進行遞歸。
尾部遞歸:
遞歸函數在調用自身後直接傳回其值,而不對其再加運算。尾部遞歸與循環是等價的,而且在一些語言(如Scheme中)可以被優化為循環指令。
因此,在這些語言中尾部遞歸不會佔用調用堆棧空間。以下Scheme程序同樣計算一個數字的階乘,但是使用尾部遞歸。
㈡ 遞歸演算法有何特點
遞歸4—遞歸的弱點
之所以沒有把這段歸為演算法的討論,因為這里討論的不在是演算法,而只是討論一下濫用遞歸的不好的一面。
遞歸的用法似乎是很容易的,但是遞歸還是有她的致命弱點,那就是如果運用不恰當,濫用遞歸,程序的運行效率會非常的低,低到什麼程度,低到出乎你的想像!當然,平時的小程序是看不出什麼的,但是一旦在大項目里濫用遞歸,效率問題將引起程序的實用性的大大降低!
例子:求1到200的自然數的和。
第一種做法:
#include <stdio.h>
void main()
{
int i;
int sum=0;
for(i=1;i<=200;i++)
{
sum+=i;
}
printf("%d\n",sum);
}
該代碼中使用變數2個,計算200次。再看下個代碼:
#include <stdio.h>
int add(int i)
{
if(i==1)
{
return i;
}
else
{
return i+add(i-1);
}
}
void main()
{
int i;
int sum=0;
sum=add(200);
printf("%d\n",sum);
}
但看add()函數,每次調用要聲明一個變數,每次調用要計算一次,所以應該是200個變數,200次計算,對比一下想想,如果程序要求遞歸次數非常多的時候,而且類似與這種情況,我們還能用遞歸去做嗎?這個時候寧願麻煩點去考慮其他辦法,也要嘗試擺脫遞歸的干擾。
21:21 | 添加評論 | 固定鏈接 | 引用通告 (0) | 記錄它 | 計算機與 Internet
程序演算法5—遞歸3—遞歸的再次挖掘
遞歸的魅力就在於遞歸的代碼,寫出來實在是太簡練了,而且能解決很多看起來似乎有規律但是又不是一下子能表達清楚的一些問題。思路清晰了,遞歸一寫出來問題立即就解決了,給人一重感覺,遞歸這么好用。我們在此再更深的挖掘一下遞歸的用法。
之前再強調一點,也許有人會問,你前邊的例子用遞歸似乎是更麻煩了。是,是麻煩了,因為為了方便理解,只能舉一些容易理解的例子,一般等實際應用遞歸的時候,遠遠不是這種狀態。
好了我們現在看一個數字的序列;有一組數的集合{1,2,4,7,11,16,22,29,37,46,56……}我故意多給幾項,一般是只給前4項讓你找規律的。序列給了,要求是求前50項的和。規律?有?還是沒有?一看就象有,但是又看不出來,我多給了幾項,應該很快看出來了,哦,原來每相鄰的兩項的差是個自然數排列,2-1=1,4-2=2,7-4=3,11-7=4,16-11=5……
好了,把規律找出來了,一開始可能覺得沒頭緒,沒問題,咱們把這個序列存放到一個數組總可以吧!那我們就聲明一個數組,存放前50個數據,一個一個相加總可以了。於是有了下邊的寫法:
#include <stdio.h>
void main()
{
int i,a[50],sum=0;
a[0]=1;
for(i=1;i<50;i++)
{
a[i]=a[i-1]+i;
}
for(i=0;i<50;i++)
{
sum+=a[i];
}
printf("%d\n",sum);
}
好了,代碼運行一下,結果出來了,正確不正確呢?自己測試吧,把50項改成1、2、3、4、5……項,試試前多少項是不是正確,雖然這不是正確的測試方法,但是的確是常用的測試方法。
等到這個代碼已經完全理解了,完全明白了正個計算過程,我們就應該對這段代碼進行改寫優化了,畢竟這個代碼還是不值得用一個數組的,那麼我們嘗試著只用變數去做一下:
#include <stdio.h>
void main()
{
int i;
int number=1;
int sum=0;
for(i=0;i<50;i++)
{
number+=i;
sum+=number;
}
printf("%d\n",sum);
}
不知道我這樣寫是不是跨度大了點,但是我不準備詳細解釋了,很多東西需要你去認真分析的,所以很多東西如果不懂,自己想清楚比別人解釋的效果會更好,因為別人講只能讓你理解,如果你自己去想,你就在理解的同時學會了思考。
這個代碼寫出來,不要繼續看下去,先自己嘗試著把這個題目用遞歸做一下看看自己能不能寫出來,當然,遞歸並不是那麼輕松就能使用的,有時候也是需要去細心設計的。如果做出來了,對比一下下邊的代碼,如果沒有寫出來,建議認真分析後邊的代碼,然後最好是能完全掌握,能自己隨時把這行代碼寫出來:
#include <stdio.h>
int add(int n,int num,int i)
{
num+=i;
if(i>=n-1)
{
return num;
}
else
{
return num+add(n,num,i+1);
}
}
void main()
{
int sum;
sum=add(50,1,0); /*50表示前50象項*/
printf("%d\n",sum);
}
當然這個代碼中的n只是一個參考變數,如果把if(i>=n-1)中的n該成50,那麼就不需要這個n了,函數兩個參數就可以了,這樣寫是為了修改方便。
20:28 | 添加評論 | 固定鏈接 | 引用通告 (0) | 記錄它 | 計算機與 Internet
程序演算法4—遞歸2—遞歸的魅力
兩天沒有再寫下去,因為畢竟有時候會有點心情問題,有時候覺得心情不好,一下子什麼東西都想不起來了,很多時候寫一些東西是需要狀態的,一旦狀態有了,想的東西才能順利的寫出來,雖然有些東西寫出來在別人看來很垃圾,但是起碼自己覺得還是相當滿意的,我寫這個本來就沒有多少技術含量,只是想給初學程序的人一些指引,加快他們對程序的領悟!
好了,言歸正傳,繼續上次遞歸的討論,看看遞歸的魅力所在。
有這樣一個問題,說一個猴子和一堆蘋果,猴子一天吃一半,然後再吃一個,10天後剩下一個了,也就是說吃了10次,剩下1個了。問原來一共有多少蘋果。
當然我們的目的不是求出蘋果的數量,而是尋求一種解決問題的方法,這個問題一出來,通常對程序掌握深度不一樣的朋友對這個題會有不同的認識,首先介紹一種解決方法,這種人腦袋還是比較聰明的,思路非常的明確,也有可能語言工具掌握的也不錯,代碼寫出來非常准確,先看一下代碼再做評價吧:
#include <stdio.h>
void main()
{
int day=10;
int apple;
int i,j;
for(i=1;;i++)
{
apple=i;
for(j=0;j<day;j++)
{
if(apple%2==0&&apple>0)
{
apple/=2;
apple--;
}
else
{
break;
}
}
if(j==day&&apple==1)
{
printf("%d\n",i);
return;
}
}
}
程序的大概思路很明確,簡單介紹一下,這種寫法就是從一個蘋果開始算起,for(i=1;;i++)的作用就是改變蘋果的數量,如果1個符合條件,那就試試2個,然後3個、4個一直到適合為止,里邊的for循環就是把每一次取得的蘋果的數目進行計算,如果每次都能順利的被2整除(也就是說每次都能保證猴子能正好吃一半),然後再減一一直到最後,如果最後蘋果剩下是一個而且天數正好是10天,那麼就輸出一下蘋果的數目,整個程序退出,如果看不明白的沒關系,這個寫法非常的不適用,我們叫寫出這種演算法的人傻X,雖然這種人腦袋也挺聰明,能寫出一些新鮮的寫法,但是又臟又臭,代碼既不簡練又不高效。
所以說,有時候有些人以為自己學的很好了,自己所做的一切都是最好的,這種想法是不正確的,也許有些初學者沒有什麼經驗寫出來的代碼卻更讓人容易明白點,那麼也是先看看代碼:
#include <stdio.h>
void main()
{
int day[11];
int i;
day[0]=1;
for(i=1;i<11;i++)
{
day[i]=(day[i-1]+1)*2;
}
printf("%d\n",day[10]);
}
代碼不長,而且也恰當的應用了題目中的規律,不是說要吃一半然後再吃一個嗎?那我用數組來存放每天蘋果的數量,用day[0]表示最後一天的蘋果數量,那就是剩下的一個,然後就是找規律了,什麼規律?就是如果猴子不多吃一個的話,那就是正好吃了一半,也就是說猴子當天吃了之後剩餘的蘋果的數目加1個然後再乘以2就是前一天的數目了,這樣一想這個題目就簡單的多了,於是這個題用數組就輕松的做出來了。
那麼這個代碼究竟是不是已經很好了呢,我們注意到,這里邊每個數組元素只用了一次並沒有被重復使用,再這種情況下我們是不是可以用一種方法代替數組呢?於是就有了更優化的寫法,這個寫法似乎已經是相當簡練了:
#include <stdio.h>
void main()
{
int apple=1;
int i;
for(i=0;i<10;i++)
{
apple=(apple+1)*2;
}
printf("%d\n",apple);
}
代碼寫到這里已經把問題完全抽象化了,所以我們就應該站在數學的角度去分析了。也許我們就應該結束了討論,但是偏偏這個時候,又來了遞歸,悄悄的通過美麗的調用顯示了一下她的魅力:
#include <stdio.h>
int apple(int i)
{
if(i==0)
{
return 1;
}
else
{
return (apple(i-1)+1)*2;
}
}
void main()
{
int i;
i=apple(10);
printf("%d\n",i);
}
原理都還是一樣的,但是寫出來的格式已經完全變掉了,沒有了for循環。假想一個復雜的問題遠比這個問題復雜,而且沒有固定循環次數,那麼我們再使用循環雖然也能解決問題,但是可能面臨循環難以設計、控制等問題,這個時候用遞歸可能就會讓問題變的非常的清晰。
另外說一點,一般我這里的代碼,並不是從最差到最好的,基本排列是從最差到最合適的代碼(當然是本人認為最合適的,也許還有更好的,本人能力所限了),然後最後給出一種比較違反常規的代碼,一般是不贊成用最後一種代碼的,當然有時候最後一種代碼也許是最好的選擇,看情況吧!
20:25 | 添加評論 | 固定鏈接 | 引用通告 (0) | 記錄它 | 計算機與 Internet
10月15日
程序演算法3—遞歸1—遞歸小顯威力
現在用C語言實現一個字元串的倒序輸出,當然,方法也是很多的,但是如果程序中能有相對優化的方法或者簡單明了易讀的方法,那對你自己或者別人都是一種幸福。
第一種寫法,這類寫法既浪費內存又不實用,一般是剛學程序的才這樣做,程序的結構很簡單,利用的是數組:
#include <stdio.h>
void main()
{
char c[2000];
int i,length=0;
for(i=0;i<2000;i++)
{
scanf("%c",&c[i]);
if(c[i]=='\n')
{
break;
}
else
{
length++;
}
}
for(i=length;i>0;i--)
{
printf("%c",c[i-1]);
}
printf("\n");
}
這段代碼中的數組,聲明大了浪費內存空間,聲明小了又怕不夠,所以寫這種代碼的人一般寫完之後會祈禱,祈禱測試的人不要輸入的太多,太多就不能完全顯示了!
與其這么提心吊膽,於是又有人想出了第二種方法,終於解決了一些問題,而且完全實現了程序的實際要求,於是,這種人經過一番苦想,覺得問題終於可以解決了,這種方法看起來是一種很不錯的方法。
#include <stdio.h>
#include <malloc.h>
void main()
{
int i;
char *c;
c=(char *)malloc(1*sizeof(char));
for(i=0;;i++)
{
*(c+i)=getchar();
if(*(c+i)=='\n')
{
*(c+i)='\0';
break;
}
else
c=(char *)realloc(c,(i+2)*sizeof(char));
}
for(--i;i>=0;i--)
{
putchar(*(c+i));
}
printf("\n");
free(c);
}
怎麼樣?不錯,准確的應用內存,幾乎沒有浪費什麼空間,這種方法也體現了一下指針的強大功能,寫這個程序雖然不敢說這個人已經掌握了指針的應用,但是起碼可以說他已經會用指針了。代碼寫出來,看起來已經有點美感。
但是也有一些人還是比較喜歡動腦筋的,經過一番思考,終於想出了第三種比較容易寫的方法,也許有寫初學者可能覺得有些難度,但是事實上這個東西一點都不難,如果稍微有點程序功底之後再看這段代碼,應該是相當輕松!
#include <stdio.h>
void run()
{
char c;
c=getchar();
if(c!='\n')
{
run();
}
else
{
return;
}
putchar(c);
}
void main()
{
run();
printf("\n");
}
寫出的代碼讓人眼前一亮,哇!原來遞歸功能簡單而又好用,那我們為什麼不好好利用呢?但是遞歸也不一定就是最好的選擇,因為有時候雖然遞歸用起來很方便,但是效率卻不高,以後的討論中還會詳細說明。
㈢ 什麼是遞歸演算法
遞歸演算法就是一個函數通過不斷對自己的調用而求得最終結果的一種思維巧妙但是開銷很大的演算法。
比如:
漢諾塔的遞歸演算法:
void move(char x,char y){
printf("%c-->%c\n",x,y);
}
void hanoi(int n,char one,char two,char three){
/*將n個盤從one座藉助two座,移到three座*/
if(n==1) move(one,three);
else{
hanoi(n-1,one,three,two);
move(one,three);
hanoi(n-1,two,one,three);
}
}
main(){
int n;
printf("input the number of diskes:");
scanf("%d",&n);
printf("The step to moving %3d diskes:\n",n);
hanoi(n,'A','B','C');
}
我說下遞歸的理解方法
首先:對於遞歸這一類函數,你不要糾結於他是干什麼的,只要知道他的一個模糊功能是什麼就行,等於把他想像成一個能實現某項功能的黑盒子,而不去管它的內部操作先,好,我們來看下漢諾塔是怎麼樣解決的
首先按我上面說的把遞歸函數想像成某個功能的黑盒子,void hanoi(int n,char one,char two,char three); 這個遞歸函數的功能是:能將n個由小到大放置的小長方形從one 位置,經過two位置 移動到three位置。那麼你的主程序要解決的問題是要將m個的"漢諾塊"由A藉助B移動到C,根據我們上面說的漢諾塔的功能,我相信傻子也知道在主函數中寫道:hanoi(m,A,B,C)就能實現將m個塊由A藉助B碼放到C,對吧?所以,mian函數裡面有hanoi(m,'A','C','B');這個調用。
接下來我們看看要實現hannoi的這個功能,hannoi函數應該幹些什麼?
在hannoi函數里有這么三行
hanoi(n-1,one,three,two);
move(one,three);
hanoi(n-1,two,one,three);
同樣以黑盒子的思想看待他,要想把n個塊由A經過B搬到C去,是不是可以分為上面三步呢?
這三部是:第一步將除了最後最長的那一塊以外的n-1塊由one位置經由three搬到two 也就是從A由C搬到B 然後把最下面最長那一塊用move函數把他從A直接搬到C 完事後 第三步再次將剛剛的n-1塊藉助hannoi函數的功能從B由A搬回到C 這樣的三步實習了n塊由A經過B到C這樣一個功能,同樣你不用糾結於hanoi函數到底如何實現這個功能的,只要知道他有這么一個神奇的功能就行
最後:遞歸都有收尾的時候對吧,收尾就是當只有一塊的時候漢諾塔怎麼個玩法呢?很簡單吧,直接把那一塊有Amove到C我們就完成了,所以hanoni這個函數最後還要加上 if(n==1)move(one,three);(當只有一塊時,直接有Amove到C位置就行)這么一個條件就能實現hanoin函數n>=1時將n個塊由A經由B搬到C的完整功能了。
遞歸這個復雜的思想就是這樣簡單解決的,呵呵 不知道你看懂沒?純手打,希望能幫你理解遞歸
總結起來就是不要管遞歸的具體實現細節步驟,只要知道他的功能是什麼,然後利用他自己的功能通過調用他自己去解決自己的功能(好繞口啊,日)最後加上一個極限情況的條件即可,比如上面說的1個的情況。
㈣ 計算機數學-遞歸演算法
你去搜搜斐波那列奇數,還有爬台階問題,這個問題類似的,fn=f(n-1)+f(n-2),希望能幫到你吧,牛客網裡面編程訓練的劍指offer也有這題
㈤ 遞歸演算法是什麼
遞歸演算法(英語:recursion algorithm)在計算機科學中是指一種通過重復將問題分解為同類的子問題而解決問題的方法。
遞歸式方法可以被用於解決很多的計算機科學問題,因此它是計算機科學中十分重要的一個概念。絕大多數編程語言支持函數的自調用,在這些語言中函數可以通過調用自身來進行遞歸。
計算理論可以證明遞歸的作用可以完全取代循環,因此在很多函數編程語言(如Scheme)中習慣用遞歸來實現循環。
㈥ 什麼是遞歸演算法有什麼作用
作者名:不詳 來源:網友提供 05年7月7日
無法貼圖 ,自己到 http://51zk.csai.cn/sjjg/NO00223.htm 看去吧
1、調用子程序的含義:
在過程和函數的學習中,我們知道調用子程序的一般形式是:主程序調用子程序A,子程序A調用子程序B,如圖如示,這個過程實際上是:
@當主程序執行到調用子程序A語句時,系統保存一些必要的現場數據,然後執行類似於BASIC語言的GOTO語句,跳轉到子程序A(為了說得簡單些,我這里忽略了參數傳遞這個過程)。
@當子程序A執行到調用子程序B語句時,系統作法如上,跳轉到子程序B。
@子程序B執行完所有語句後,跳轉回子程序A調用子程序B語句的下一條語句(我這又忽略了返回值處理)
@子程序A執行完後,跳轉回主程序調用子程序A語句的下一條語句
@主程序執行到結束。
做個比較:我在吃飯(執行主程序)吃到一半時,某人叫我(執行子程序A),話正說到一半,電話又響了起來(執行子程序B),我只要先接完電話,再和某人把話說完,最後把飯吃完(我這飯吃得也夠累的了J)。
2、認識遞歸函數
我們在高中時都學過數學歸納法,例:
求 n!
我們可以把n!這么定義
也就是說要求3!,我們必須先求出2!,要求2!,必須先求1!,要求1!,就必須先求0!,而0!=1,所以1!=0!*1=1,再進而求2!,3!。分別用函數表示,則如圖:
我們可以觀察到,除計算0!子程序外,其他的子程序基本相似,我們可以設計這么一個子程序:
int factorial(int i){
int res;
res=factorial(I-1)*i;
return res;
}
那麼當執行主程序語句s=factorial(3)時,就會執行factorial(3),但在執行factorial(3),又會調用factorial(2),這時大家要注意,factorial(3)和factorial(2)雖然是同一個代碼段,但在內存中它的數據區是兩份!而執行factorial(2)時又會調用factorial(1),執行factorial(1)時又會調用factorial(0),每調用一次factorial函數,它就會在內存中新增一個數據區,那麼這些復制了多份的函數大家可以把它看成是多個不同名的函數來理解;
但我們這個函數有點問題,在執行factorial(0)時,它又會調用factorial(-1)。。。造成死循環,也就是說,在factorial函數中,我們要在適當的時候保證不再調用該函數,也就是不執行res=factorial(I-1)*i;這條調用語句。所以函數要改成:
int factorial(int i){
int res;
if (I>0) res=factorial(I-1)*i; else res=1;
return res;
}
那麼求3!的實際執行過程如圖所示:
3、如何考慮用遞歸的方法來解決問題
例:求s=1+2+3+4+5+6+……+n
本來這個問題我們過去常用循環累加的方法。而這里如要用遞歸的方法,必須考慮兩點:
1) 能否把問題轉化成遞歸形式的描述;
2) 是否有遞歸結束的邊界條件。
設:函數s(n)=1+2+3+…+(n-1)+n
顯然遞歸的兩個條件都有了:
1) s(n) =s(n-1)+n
2) s(1)=1
所以源程序為:
int progression(int n){
int res;
if (n=1 )res=1 else res=progression(n-1)+n;
return res;
}
4、遞歸的應用
中序遍歷二叉樹
void inorder (BinTree T){
if (T){
inorder(T->lchild);
printf(「%c」,T->data);
inorder(T->rchild);
}
}
現假設樹如圖(為了講解方便,樹很簡單)
@執行第一次調用inorder1,T指向頂結點,T不為空,所以第二次調用inorder2;
@T指向頂結點的左子樹結點也就是B,不為空,所以第三次調用inorder3;
@T指向B結點的左子樹結點,為空,所以什麼都不執行,返回inorder2;
@列印B結點的DATA域值「b」;
@第四次調用inorder4,去訪問B子樹的右結點
@T指向B結點的右子樹結點,為空,所以什麼都不執行,返回inorder2;
@返回inorder1;
@列印A結點的DATA域值「a」;
@第五次調用inorder5,去訪問A子樹的右結點;
@T指向A結點的右子樹結點,為空,所以什麼都不執行,返回inorder1;
@inorder1執行完畢,返回。
㈦ 遞歸演算法
0+1 =1
1+1 =2
1+2 =3
2+3 = 5
3+5 =8
.....
an = a(n-1)+a(n-2)
sn = a1+a2+....+an=......
時間有限後面的自己夠定吧
㈧ 什麼是遞歸演算法
遞歸做為一種演算法在程序設計語言中廣泛應用.是指函數/過程/子程序在運行過程序中直接或間接調用自身而產生的重入現像.
程序調用自身的編程技巧稱為遞歸( recursion)。
一個過程或函數在其定義或說明中又直接或間接調用自身的一種方法,它通常把一個大型復雜的問題層層轉化為一個與原問題相似的規模較小的問題來求解,遞歸策略只需少量的程序就可描述出解題過程所需要的多次重復計算,大大地減少了程序的代碼量。遞歸的能力在於用有限的語句來定義對象的無限集合。用遞歸思想寫出的程序往往十分簡潔易懂。
一般來說,遞歸需要有邊界條件、遞歸前進段和遞歸返回段。當邊界條件不滿足時,遞歸前進;當邊界條件滿足時,遞歸返回。
注意:
(1) 遞歸就是在過程或函數里調用自身;
(2) 在使用遞增歸策略時,必須有一個明確的遞歸結束條件,稱為遞歸出口,否則將無限進行下去(死鎖)。
遞歸演算法一般用於解決三類問題:
(1)數據的定義是按遞歸定義的。(Fibonacci函數)
(2)問題解法按遞歸演算法實現。(回溯)
(3)數據的結構形式是按遞歸定義的。(樹的遍歷,圖的搜索)
遞歸的缺點:
遞歸演算法解題的運行效率較低。在遞歸調用的過程當中系統為每一層的返回點、局部量等開辟了棧來存儲。遞歸次數過多容易造成棧溢出等。
㈨ 遞歸演算法的是怎麼回事
和迭代差不多,只是通過定義和調用函數來實現迭代
把事情分解成相同的步驟重復執行直到符合某一條件時結束,再反過來遞推到最初的狀態,問題就解決了
比如定義(用的是C語言)
int fun(int a)
{
if(a==1) return 1;
else
{
a=a*fun(a-1);
return a;
}
}
在fun裡面再定義fun,這個fun都只做一件事,把a的內容和fun(a-1)相乘作為返回值
這里要有個終止條件,即a=1時返回值為1,這樣,如果我給最初的fun里的a賦值為5,第一步為5*fun(4),而執行fun(4)的結果為4*fun(3)....直到fun(2)=2*fun(1)即fun(2)=2*1,再把fun(2)代回去,得fun(3)=3*2*1,最後倒推的結果為fun(5)=5*4*3*2*1,即這個遞歸函數實現了a的階乘fun(a)=a!
夠詳細了吧,覺得好的話給我加分吧 ^_^
㈩ 樹的遞歸演算法
答案是正確的啊。
if(root)就是如果root!=0,這里root是一個指針,指向結構體struct node的指針,第一次進入函數它就是指向根節點A的指針
運行步驟:
如果指向A的指針不為空(不為0),列印'A',
遞歸調用函數指向A的左孩子節點
如果指向B的指針不為空(不為0),列印'B',
遞歸調用函數指向B的左孩子節點
如果指向C的指針不為空(不為0),列印'C',
遞歸調用函數指向C的左孩子節點
由於C的左孩子節點為空,所以本次遞歸traversal(root->lchild)結束,回到上一層遞歸中即從C的左孩子節點回到C中,然後執行traversal(root->lchild)這一句下面一句,列印出'C'
然後遞歸調用traversal(root->rchild);指向C的右孩子節點
如果指向E的指針不為空(不為0),列印'E',
然後再遞歸指向E的左孩子節點,為空再返回到E中,再次列印出'E',然後再指向E的右孩子節點,為空,E的遞歸結束返回上一層遞歸即C中,然後C也到達末尾結束返回上一層遞歸B中,然後執行traversal(root->lchild)這一句下面一句,列印出'B'
然後遞歸調用traversal(root->rchild);指向B的右孩子節點
......
如此不斷進入某個節點的子節點操作後再從子節點返回父節點,層層進入再層層向上返回,從而遍歷樹中各個節點,最終得出結果:
A B C C E E B A D F F D G G