二叉樹的非遞迴遍歷(c c )

2021-10-02 16:21:53 字數 3290 閱讀 9838

由於遞迴演算法相對於非遞迴演算法來說效率通常都會更低,遞迴演算法會有更多的資源需要壓棧和出棧操作(不僅僅是引數,還有函式位址等)由於編譯器對附加的一些棧保護機制會導致遞迴執行的更加低效,使用迴圈代替遞迴演算法,通常可以獲得更好的執行效率和空間效率,在二叉樹層次較深的情況下,採用非遞迴方式遍歷能夠有效的提公升遍歷的效能。

二叉樹的非遞迴遍歷分為三種:先序非遞迴遍歷,中序非遞迴遍歷和後續非遞迴遍歷。這和遞迴遍歷的結果是一樣的,區別只是在於採用了迴圈結構。

先序非遞迴遍歷

採用輔助資料結構棧來實現,先序遍歷是按照先根,後左子樹,再右子樹的順序進行遞迴訪問的。由於棧是先入後出的,所以入棧順序為先右孩子後左孩子。

非遞迴的演算法是先將根結點入棧,棧不為空時:根結點出棧並訪問,然後將右孩子入棧,再將左孩子入棧;左孩子出棧並訪問,它的孩子也是按照先右後左順序分別入棧,如此往復直至棧為空結束。**如下:

void

preordernorecursion

(btnode* p)

}}

先序非遞迴根結點先入棧,然後以棧不為空為迴圈判定條件。

中序非遞迴遍歷

輔助資料結構仍採用棧,為實現左-根-右的訪問順序,中序遍歷的第乙個結點為最左邊的那個結點,據此,可以先從根結點開始入棧,沿著最左邊的那條分支依次入棧,這樣棧頂元素就是中序遍歷中的第乙個結點了。

接下來需要做的是當棧中元素出棧並被訪問後,若該結點有右孩子怎麼辦?這時,從該結點的右孩子開始,按照最左邊分支將結點依次入棧,出棧時進行訪問。由此往復,直至結束。**如下:

void

inordernorecursion

(btnode* p)

if(top!=-1

)//出棧時temp指向出棧結點的右孩子,進行下一輪迴圈

}}

中序非遞迴遍歷根結點先不入棧,迴圈判定條件有兩個。

後序非遞迴遍歷

這裡列出一種比較好理解的後續非遞迴遍歷,它的思路可以看下面的例子

對上圖中的a,b,c三個結點來講:

先序遍歷為:a,b,c

後序遍歷為:b,c,a

二者之間的聯絡在於,如果將先序遍歷順序的根-左-右改為根-右-左,即交換訪問次序,遍歷結果為a,c,b,然後將其結果逆序,得b,c,a。這剛好是後序遍歷的結果。

對上圖中的所有結點來講:

先序遍歷為:a,b,d,e,c,f

交換次序後的結果為:a,c,f,b,e,d

再逆序:d,e,b,f,c,a

而後序遍歷的結果也為:d,e,b,f,c,a

由此可得:

先序+交換+逆序=後序

void

postordernorecursion

(btnode* p)

while

(top2 !=-1

)//再逆序

std::cout << stack2[top2--]-

>data <<

' ';

//訪問棧2中的資料

}}

完整示例

關於二叉樹非遞迴遍歷的完整**如下:

#include

typedef

struct btnode

btnode;

btnode*

initial

(char

* ele,

int num)

;//用陣列初始化一棵樹

void

level

(btnode* p)

;//層序遍歷

void

preordernorecursion

(btnode* p)

;//先序非遞迴遍歷

void

inordernorecursion

(btnode* p)

;//中序非遞迴遍歷

void

postordernorecursion

(btnode* p)

;//後序非遞迴遍歷

intmain()

; btnode* p =

initial

(data,6)

; cout <<

"先序非遞迴遍歷: "

;preordernorecursion

(p);

cout << endl;

cout <<

"中序非遞迴遍歷: "

;inordernorecursion

(p);

cout << endl;

cout <<

"後序非遞迴遍歷: "

;postordernorecursion

(p);

cout << endl;

cout <<

"層序遍歷: "

;level

(p);

cout << endl;

return0;

}btnode*

initial

(char

* ele,

int num)

i =0;

while

(i < num/2)

//通過完全二叉樹的順序儲存來建立樹的結構

for(i =

0; i < num; i++

)//對樹中的每個結點賦值

temp[i]

.data = ele[i]

;return temp;

}void

preordernorecursion

(btnode* p)}}

void

inordernorecursion

(btnode* p)

if(top!=-1

)//出棧時temp指向出棧結點的右孩子,進行下一輪迴圈}}

void

postordernorecursion

(btnode* p)

while

(top2 !=-1

) std::cout << stack2[top2--]-

>data <<

' ';}}

void

level

(btnode* p)

if(que[front]

->rc !=

null)}

}}

二叉樹遍歷(遞迴 非遞迴)

二叉樹以及對二叉樹的三種遍歷 先根,中根,後根 的遞迴遍歷演算法實現,以及先根遍歷的非遞迴實現。node public class node public node left public node right public object value 遍歷訪問操作介面 public inte ce ...

二叉樹非遞迴遍歷

二叉樹非遞迴遍歷的幾個要點 1 不管前序 中序還是後序,它們的遍歷路線 或者說是回溯路線,先沿左邊一直走到盡頭,然後回溯到某節點,並跳轉到該節點的右孩子 如果有的話 然後又沿著這個有孩子的左邊一直走到盡頭 都是一樣的。2 明確每次回溯的目的。比如,前序回溯的目的是為了訪問右子樹 中序回溯的目的是為了...

非遞迴遍歷二叉樹

中序遞迴遍歷 void inordertrvdigui node pnode 然而,當樹的深度很大 比如16 時 假設為滿二叉樹 樹的節點數為 2 0 2 1 2 2 2 15 2 16 65536,遍歷整個二叉樹意味著有65536次函式呼叫,這將極大地增加程式執行時間。這時,應該採取非遞迴便利二叉...