二叉樹遍歷(遞歸算法和非遞歸算法)

實驗三? 二叉樹遍歷(遞歸算法和非遞歸算法)

一.實驗?zāi)康?/b>

1.掌握二叉樹的存儲結(jié)構(gòu)與基本操作

2.掌握二叉樹的遍歷算法

二.實驗要求與內(nèi)容

1. 建立二叉樹,采用遞歸的方式完成前炒刁、中琴儿、后三種遍歷立宜。(建立二叉樹的算法參考課本P174)

2. 建立二叉樹腻豌,采用非遞歸的方式完成前、中儡炼、后三種遍歷响牛。

三.實驗步驟

1.?dāng)?shù)據(jù)結(jié)構(gòu)

遞歸算法只需要定義一個結(jié)構(gòu)體儲存各個節(jié)點信息玷禽,而非遞歸算法需要多定義一個棧來儲存遍歷時的信息赫段。在非遞歸算法的后序遍歷中還需要創(chuàng)建一個一維數(shù)組用來做標(biāo)識結(jié)點的左右子樹樹否都遍歷過。詳細(xì)解釋請看附錄中結(jié)合代碼的解釋矢赁。

2.算法設(shè)計

遞歸算法根據(jù)不同的遍歷方式采取不同遞歸調(diào)用遍歷順序即可糯笙。

非遞歸算法

前序遍歷的核心思想:當(dāng)node所指的結(jié)點不為空時,訪問該結(jié)點即輸出該結(jié)點的信息并將該結(jié)點所在的鏈接點的地址進棧撩银,然后再將node指向該結(jié)點的左子樹给涕;當(dāng)node所指的結(jié)點為空時,則從棧中退出棧頂元素給node额获,然后將該node指向該結(jié)點的右孩子結(jié)點够庙。重復(fù)上述過程,直至node為NULL抄邀,并且棧也為空耘眨,遍歷結(jié)束。

中序遍歷的核心思想:當(dāng)node所指的結(jié)點不為空時撤摸,則將該結(jié)點所在的鏈接點的地址進棧,然后再將node指向該結(jié)點的左子樹褒纲;當(dāng)node所指的結(jié)點為空時准夷,則從棧中退出棧頂元素給node,訪問該結(jié)點即輸出該結(jié)點的信息莺掠,然后將該node指向該結(jié)點的右孩子結(jié)點衫嵌。重復(fù)上述過程,直至node為NULL彻秆,并且棧也為空楔绞,遍歷結(jié)束。

后序遍歷的核心思想:當(dāng)node指向某一個結(jié)點時唇兑,不能馬上對它進行訪問酒朵,而要先遍歷它的左子樹,因而要將該結(jié)點的地址進棧扎附,當(dāng)其左子樹遍歷完畢以后蔫耽,再次搜索要該結(jié)點時(該結(jié)點的地址通過退棧得到),還不能對它進行訪問留夜,還需要遍歷它的右子樹匙铡,所以,將該結(jié)點的地址再一次進棧碍粥。只有該結(jié)點的右子樹被遍歷以后回到該結(jié)點鳖眼,才訪問該結(jié)點,為了標(biāo)明某結(jié)點是否可以被訪問嚼摩,引入一個標(biāo)志變量標(biāo)明钦讳。

3.程序

void bulidtree(bitree &T)//二叉樹的建立(按照前序遍歷建立二叉樹)

{

? ? char c;

? ? cin>>c;

? ? if(c=='#')//判斷該節(jié)點是否存在

? ? ? ? T =NULL;

? ? else

? ? {

? ? ? ? T=new bitreenode;

? ? ? ? T->date=c;

? ? ? ? bulidtree(T->left);//建立左子樹

? ? ? ? bulidtree(T->right);//建立右子樹

? ? }


}

//中序后序的遞歸算法類似于前序只改變了輸出位置

void front(bitree T)//前序遍歷二叉樹

{

? ? if(T!=NULL)

? ? {

? ? ? ? cout<<T->date<<" ";

? ? ? ? front(T->left);

? ? ? ? front(T->right);

? ? }


}

//非遞歸前序遍歷矿瘦,中序遍歷類似于前序遍歷

void front1(bitree T){

? ? if(T){

? ? ? ? Stack s;

? ? ? ? init(s.top);

? ? ? ? bitree node =T;

? ? ? ? while(node!=NULL||!empty(s.top)){//當(dāng)結(jié)點為空并且棧也為空時退出

? ? ? ? ? ? while(node!=NULL){//當(dāng)結(jié)點不為空時輸出該結(jié)點并將該結(jié)點壓入棧并遍歷左子樹

? ? ? ? ? ? ? ? printf("%c ",node->date);

? ? ? ? ? ? ? ? push(&s,node);

? ? ? ? ? ? ? ? node=node->left;

? ? ? ? ? ? }

? ? ? ? ? ? if(!empty(s.top)){//結(jié)點為NULL但是棧不為空

? ? ? ? ? ? ? ? node=pop(&s);//彈出棧頂元素并賦給node

? ? ? ? ? ? ? ? node=node->right;//遍歷結(jié)點的右子樹

? ? ? ? ? ? }

? ? ? ? }


? ? }

}

//后序遍歷

?void back1(bitree T){

?int b[20];

?if(T){

?Stack s;

?init(s.top);

?bitree node =T;

?while(node!=NULL || !empty(s.top)){

?while(node!=NULL){

?push(&s,node);//第一次進棧

?b[s.top]=0;

?node=node->left;

?}

?node=pop(&s);

?int flag=b[s.top+1];

?if(flag==0){? //說明只進過一次

?push(&s,node);//第二次進棧

?b[s.top]=1;

?node=node->right;

?}

?else{? ? //已經(jīng)進過兩次棧,說明左右子樹都已經(jīng)遍歷過了

?printf("%c ",node->date);

?node=NULL;

?}

?}

?}

?}

4.程序調(diào)試

測試數(shù)據(jù)蜂厅、程序運行結(jié)果截圖?

四.結(jié)果與體會

該實驗的難點在于非遞歸算法的設(shè)計匪凡,剛開始的時候沒有想法,后面參考書上的方法發(fā)現(xiàn)可以用while或則do..while在一定程度上代替遞歸算法實現(xiàn)相同的目的掘猿,比如遞歸實現(xiàn)找到最左子樹可以用while(node->left!=NULL)實現(xiàn)病游。

五.源程序

另附

#include<iostream>

using namespace std;

typedef struct node{

? ? node *left;

? ? node *right;

? ? char date;

}bitreenode,*bitree;

typedef struct {

? ? bitree stack[100];

? ? int top;

}Stack;

void init(int &top){

? ? top=-1;

}

int full(int top){

? ? return top==99;

}

int empty(int top){

? ? return top==-1;

}

int push(Stack *s,bitree a){

? ? int top1=s->top;

? ? if(a==NULL)

? ? ? ? return 0;

? ? else

? ? {

? ? ? ? s->top++;

? ? ? ? s->stack[++top1]=a;

? ? ? ? return 1;

? ? }

}

bitree pop(Stack *s){

? ? int top1=s->top;

? ? if (top1!=-1){

? ? ? ? s->top--;

? ? ? ? return s->stack[s->top+1];

? ? }

? ? else

? ? ? ? return NULL;

}

void bulidtree(bitree &T)//二叉樹的建立(按照前序遍歷建立二叉樹)

{

? ? char c;

? ? cin>>c;

? ? if(c=='#')//判斷該節(jié)點是否存在

? ? ? ? T =NULL;

? ? else

? ? {

? ? ? ? T=new bitreenode;

? ? ? ? T->date=c;

? ? ? ? bulidtree(T->left);//建立左子樹

? ? ? ? bulidtree(T->right);//建立右子樹

? ? }


}

void front(bitree T)//前序遍歷二叉樹

{

? ? if(T!=NULL)

? ? {

? ? ? ? cout<<T->date<<" ";

? ? ? ? front(T->left);

? ? ? ? front(T->right);

? ? }


}

void mid(bitree T)//中序遍歷二叉樹

{

? ? if(T!=NULL)

? ? {

? ? ? ? mid(T->left);

? ? ? ? cout<<T->date<<" ";

? ? ? ? mid(T->right);

? ? }


}

void back(bitree T)//后序遍歷二叉樹

{

? ? if(T!=NULL)

? ? {

? ? ? ? back(T->left);

? ? ? ? back(T->right);

? ? ? ? cout<<T->date<<" ";

? ? }


}

//非遞歸前序遍歷

void front1(bitree T){

? ? if(T){

? ? ? ? Stack s;

? ? ? ? init(s.top);

? ? ? ? bitree node =T;

? ? ? ? while(node!=NULL||!empty(s.top)){//當(dāng)結(jié)點為空并且棧也為空時退出

? ? ? ? ? ? while(node!=NULL){//當(dāng)結(jié)點不為空時輸出該結(jié)點并將該結(jié)點壓入棧并遍歷左子樹

? ? ? ? ? ? ? ? printf("%c ",node->date);

? ? ? ? ? ? ? ? push(&s,node);

? ? ? ? ? ? ? ? node=node->left;

? ? ? ? ? ? }

? ? ? ? ? ? if(!empty(s.top)){//結(jié)點為NULL但是棧不為空

? ? ? ? ? ? ? ? node=pop(&s);//彈出棧頂元素并賦給node

? ? ? ? ? ? ? ? node=node->right;//遍歷結(jié)點的右子樹

? ? ? ? ? ? }

? ? ? ? }


? ? }

}

//中序遍歷

void mid1(bitree T){

? ? if(T){

? ? ? ? Stack s;

? ? ? ? init(s.top);

? ? ? ? bitree node =T;

? ? ? ? while(node!=NULL || !empty(s.top)){

? ? ? ? ? ? while(node!=NULL){

? ? ? ? ? ? ? ? push(&s,node);

? ? ? ? ? ? ? ? node=node->left;

? ? ? ? ? ? }

? ? ? ? ? ? if(!empty(s.top)){

? ? ? ? ? ? ? ? node=pop(&s);

? ? ? ? ? ? ? ? printf("%c ",node->date);

? ? ? ? ? ? ? ? node=node->right;

? ? ? ? ? ? }

? ? ? ? }

? ? }


}

?//后序遍歷

?void back1(bitree T){

?int b[20];

?if(T){

?Stack s;

?init(s.top);

?bitree node =T;

?while(node!=NULL || !empty(s.top)){

?while(node!=NULL){

?push(&s,node);//第一次進棧

?b[s.top]=0;

?node=node->left;

?}

?node=pop(&s);

?int flag=b[s.top+1];

?if(flag==0){? //說明只進過一次

?push(&s,node);//第二次進棧

?b[s.top]=1;

?node=node->right;

?}

?else{? ? //已經(jīng)進過兩次棧,說明左右子樹都已經(jīng)遍歷過了

?printf("%c ",node->date);

?node=NULL;

?}

?}

?}

?}

int main()

{

? ? bitree T;

? ? cout<<"開始建立二叉樹"<<endl;

? ? cout<<"請按照前序遍歷輸入二叉樹信息"<<endl;

? ? bulidtree(T);

? ? cout<<"二叉樹創(chuàng)建成功"<<endl;

? ? cout<<"遞歸方式"<<endl;

? ? cout<<"前序遍歷: ";

? ? front(T);

? ? cout<<endl;

? ? cout<<"中序遍歷: ";

? ? mid(T);

? ? cout<<endl;

? ? cout<<"后續(xù)遍歷: ";

? ? back(T);

? ? cout<<endl;

? ? cout<<"非遞歸方式: "<<endl;

? ? cout<<"前序遍歷: ";

? ? front1(T);

? ? cout<<endl;

? ? cout<<"中序遍歷: ";

? ? mid1(T);

? ? cout<<endl;

? ? cout<<"后續(xù)遍歷: ";

? ? back1(T);

? ? cout<<endl;

? ? return 0;

?}

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末稠通,一起剝皮案震驚了整個濱河市衬衬,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌改橘,老刑警劉巖滋尉,帶你破解...
    沈念sama閱讀 206,839評論 6 482
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異飞主,居然都是意外死亡狮惜,警方通過查閱死者的電腦和手機,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,543評論 2 382
  • 文/潘曉璐 我一進店門碌识,熙熙樓的掌柜王于貴愁眉苦臉地迎上來碾篡,“玉大人,你說我怎么就攤上這事筏餐】螅” “怎么了?”我有些...
    開封第一講書人閱讀 153,116評論 0 344
  • 文/不壞的土叔 我叫張陵魁瞪,是天一觀的道長穆律。 經(jīng)常有香客問我,道長导俘,這世上最難降的妖魔是什么峦耘? 我笑而不...
    開封第一講書人閱讀 55,371評論 1 279
  • 正文 為了忘掉前任,我火速辦了婚禮旅薄,結(jié)果婚禮上贡歧,老公的妹妹穿的比我還像新娘。我一直安慰自己赋秀,他們只是感情好利朵,可當(dāng)我...
    茶點故事閱讀 64,384評論 5 374
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著猎莲,像睡著了一般绍弟。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上著洼,一...
    開封第一講書人閱讀 49,111評論 1 285
  • 那天樟遣,我揣著相機與錄音而叼,去河邊找鬼。 笑死豹悬,一個胖子當(dāng)著我的面吹牛葵陵,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播瞻佛,決...
    沈念sama閱讀 38,416評論 3 400
  • 文/蒼蘭香墨 我猛地睜開眼脱篙,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了伤柄?” 一聲冷哼從身側(cè)響起绊困,我...
    開封第一講書人閱讀 37,053評論 0 259
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎适刀,沒想到半個月后秤朗,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 43,558評論 1 300
  • 正文 獨居荒郊野嶺守林人離奇死亡笔喉,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 36,007評論 2 325
  • 正文 我和宋清朗相戀三年取视,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片常挚。...
    茶點故事閱讀 38,117評論 1 334
  • 序言:一個原本活蹦亂跳的男人離奇死亡作谭,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出待侵,到底是詐尸還是另有隱情丢早,我是刑警寧澤姨裸,帶...
    沈念sama閱讀 33,756評論 4 324
  • 正文 年R本政府宣布秧倾,位于F島的核電站,受9級特大地震影響傀缩,放射性物質(zhì)發(fā)生泄漏那先。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 39,324評論 3 307
  • 文/蒙蒙 一赡艰、第九天 我趴在偏房一處隱蔽的房頂上張望售淡。 院中可真熱鬧,春花似錦慷垮、人聲如沸揖闸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,315評論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽汤纸。三九已至,卻和暖如春芹血,著一層夾襖步出監(jiān)牢的瞬間贮泞,已是汗流浹背楞慈。 一陣腳步聲響...
    開封第一講書人閱讀 31,539評論 1 262
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留啃擦,地道東北人囊蓝。 一個月前我還...
    沈念sama閱讀 45,578評論 2 355
  • 正文 我出身青樓,卻偏偏與公主長得像令蛉,于是被迫代替她去往敵國和親聚霜。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 42,877評論 2 345

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