二叉樹的兩種遍歷方法

2021-08-22 02:25:51 字數 3101 閱讀 6959

二叉樹的遍歷有兩種方式,一種是遞迴遍歷,另一種是非遞迴遍歷。

前一種方法從形式上很好理解,在這裡不再過多的談論,直接上**。

二叉樹的建立

//定義並通過層序生成一棵二叉樹

typedef

struct bitreebitree;

bitree* creatbitree();

bitree** con[max]={};

int idxa=1;

int idxc1=0;

int idxc2=2;

for(int i=0;inull;

bitree *root=(bitree*)malloc(sizeof(bitree));

root->value=arr[0];

root->left=root->right=null;

con[0]=&(root->left);

con[1]=&(root->right);

while(idxa<6)

return root;

}

二叉樹的遞迴遍歷

int pre(bitree *t)

int in(bitree *t)

int post(bitree *t)

從**中的形式中很容易理解遍歷的順序,根據」被遍歷」節點的位置將節點進行列印輸出。

二叉樹的非遞迴遍歷

int npre(bitree *t);

int top=0;

bitree *poped=null;

bitree *q=t;

while(top>0||q)

else}}

}int nin(bitree *t);

int top=0;

bitree* q=t;

while(q||top>0)

else

}}int npost(bitree *t);

int top=0;

bitree *q=t;

bitree *poped=null;

while(q||top>0)

else

else

q=stk[top-1]->right;}}

}

二叉樹的非遞迴遍歷和遞迴遍歷本質上是相同的,只是儲存未經過遍歷變數的方式有所區別。接下來就詳細的對二叉樹的非遞迴遍歷進行說明。
1.前序(中、左、右)

由其遍歷的順序可知,如果當前節點存在,則應先輸出當前節點的值,將其儲存在棧中,並將指標指向其左子樹,對其左子樹進行判斷。

當其左子樹為空時,對於當前的這棵樹,父節點已經輸出,左子樹不存在,這時我們應該對其右子樹進一步進行判斷:1.若其右子樹不存在,則說明當前父節點已經是左側最深的節點了,此時我們應當將此節點彈出,並把指標指向null,做下一次判斷(不能指回其父節點,否則會出現多餘的遍歷)2.若其右子樹存在並且不等於剛剛彈出的節點(考慮乙個節點的右子樹不為空,但右子樹的左右子樹為空時,遍歷完其右子樹後,會彈出其右子樹,此時若不將其設定為poped,並且在判斷時加上對poped的判斷,則其右子樹會再一次被選為當前節點,於是死迴圈就出現了)則將其設定為當前節點,繼續進行遍歷。

當top=0時有兩種情況,第一是包括根節點在內的所有根節點左邊的節點遍歷完成,另一種是全部遍歷完成,此時需要對結束條件進一步判斷,前兩個的區別為top為0時」當前節點的情況」,如果是null則說明無更多的節點可以遍歷了,如果非null,則說明當前仍有節點為經遍歷,需要繼續遍歷。

2.中序(左、中、右)

中序遍歷需要我們首先對節點的左子樹(如果存在的話)進行遍歷,其次在遍歷」本節點」,最後遍歷右節點。

跟著定義出發,遍歷時如果當前節點存在則將其放入棧,並將當前節點賦為其左子樹,直到當前節點為空時,此時我們可以假定,此節點作為其父節點的左子樹已經被遍歷過了(雖然為空),所以根據順序,我們應該對此節點的父節點進行遍歷,首先將其列印出來表示以被遍歷,此時我們遇到乙個問題,是否要將其彈出呢?我們接著往下思考,1.若此節點沒有右子樹,則一定要將其彈出,否則程式無法繼續執行。2.如果此節點有右子樹,假設此時先不彈出,則我們接下來應該對其右子樹進行遍歷,某一時刻其右子樹遍歷完成並且都彈出,又到了這個節點,所以此時需要對其做判斷,但很顯然這是多餘的。綜合以上兩點,我們將其彈出。此時對此節點的右子樹進行判斷,如果為null,則將當前指標指向null,如果不為null,則將其指向右子樹。

對於結束條件的判斷與1相同。

3.後序(左、右、中)

由於本次也是先讀出節點的左子樹,所以前一部分與2相同,我們直接討論當當前指標為空的情況。當前指標指向null時,表示此節點父節點的左子樹作為null已被遍歷,此時應該考慮,其父節點的右子樹的情況。進行一下兩類判斷。1.當其父節點的右子樹為空時,表示此節點為」最左的節點」,將其列印並彈出,表示為以被遍歷,接下來我們應該考慮其父節點的父節點的右子樹的情況,到此我們只需要將當前節點設為null即可。2.當其父節點的右節點存在時,由遍歷順序可知,此時還無法對此節點的父節點及其右子樹進行列印,需要進一步判斷,所以將當前節點賦為其父節點的右子樹。

此時我們考慮一種特殊情況,當乙個節點和其右子樹存在,並且其右子樹的左右子樹不存在時,當遍歷完其右子樹,彈出其右子樹後,對此節點進行判斷,會再將其右子樹納入當前節點,於是又陷入了死迴圈,所以在後序遍歷時,我們仍然需要對剛遍歷的節點進行記錄,並在當前節點為空,對下一當前節點進行賦值時,加上此判斷。情況與前序是一致的。

總結,當我們使用非遞迴方法對二叉樹進行遍歷時,需要著重注意的是以下幾點。

1.何時列印出遍歷值

2.當」當前指標」指向null時,接下來對」當前指標」指向的判斷,我們不需要記住,寫的時候適當進行推理便很容易得出。

3.是否需要記錄已彈出的變數,我們根據這篇文章的分析可以知道,當前序(中左右)和後序(左右中)時需要對其判斷,從二者遍歷形式上來看,這兩種遍歷的」順序」是一致的,」左」和」右」相鄰,這兩個遍歷方式還有許多相似之處,比如,僅當中序便利和這兩個中任一序遍歷已知時,我們才能推出二叉樹的形狀等…在此就不在多說。

4.結束條件的判斷。

只要注意好上述四點,我們再寫出非遞迴遍歷時就會很容易了。

根據兩種二叉樹遍歷方式,求二叉樹方法

如何根據已知兩種遍歷的序列,求原始的二叉樹?並不是已知道任意兩個序列都可以還原二叉樹,只有知道先序中序以及中序和後序兩種型別的遍歷順序才能還原二叉樹。只知道先序和後序是還原不了原始的二叉樹的。1 已知道先序和中序遍歷,還原二叉樹。已知道二叉樹的先序遍歷為abcdefgh,中序遍歷為bdceafhg,...

由兩種遍歷序列確定二叉樹

已知中序和後序遍歷 typedef int elemtype typedef struct tnode position typedef position bintree typedef struct tnode bintree creat int a,int b,int n 陣列a,b分別存放中序...

二叉樹遍歷的6種遍歷方法

二叉樹遍歷的6種遍歷方法 先序遍歷,中序遍歷,後序遍歷分別用遞迴跟非遞迴實現 主要 如下 include define true 1 define false 0 define ok 1 define error 0 define infeasible 1 define overflow 2type...