-先序遍歷:
訪問根結點,先序遍歷其左子樹,先序遍歷其右子樹;運用到遞歸
void PreOrderTraversal ( BinTree BT )
{
if ( BT )
{
printf ( “%d”, BT -> Data );
PreOrderTraversal ( BT -> Left );
PreOrderTraversal ( BT -> Right );
}
}
-中序遍歷:
中序遍歷其左子樹,訪問根結點,中序遍歷其右子樹
void InOrderTraversal ( BinTree BT )
{
if ( BT )
{
InOrderTraversal ( BT -> Left );
printf ( “%d”, BT -> Data );
InOrderTraversal ( BT -> Right );
}
}
-后序遍歷:
后序遍歷其左子樹,后序遍歷其右子樹,訪問根結點
void PostOrderTraversal ( BinTree BT )
{
if ( BT )
{
PostOrderTraversal ( BT -> Left );
PostOrderTraversal ( BT -> Right );
printf ( “%d”, BT -> Data );
}
}
三種遍歷過程中經過的結點的路線一樣,只是訪問各結點的時機不同,先序中序后序分別對應第一次訪問時printfData第二次訪問printfData和第三訪問printfData
上面三種方法都是用遞歸,而遞歸根本實現方法是堆棧,現在我們直接用堆棧來實現非遞歸的遍歷算法
eg:中序遍歷非遞歸遍歷算法:
1.遇到一個結點 就把它壓棧 并去遍歷它的左子樹
2.當左子樹遍歷結束后 從棧頂彈出這個結點并訪問它
3.然后按其右指針再去中序遍歷該結點的右子樹
void InOrderTraversal( BinTree BT ){
Stack s = CreateStack ( MaxSize ) // 創建并初始化堆棧s
while( T | | !IsEmpty(s) ){
while(T){ // 一直向左并將沿途結點壓入堆棧
Push ( S, T );
T = T -> Left;
}
if ( !IsEmpty(s) ){
T = Pop(s); // 結點彈出堆棧
printf(“]”, T -> Data); //(訪問)打印結點
T = T -> Right; //轉向右子樹
}
}
-層序遍歷:
二叉樹遍歷的核心問題:二維結構的線性化
一個結點有兩個關聯(左兒子和右兒子)通過一個結點訪問到一個關聯結點(左兒子)后另一個關聯結點(右兒子)怎么辦?這個結點本身怎么辦?這就需要將二維結構線性化。
解決方案:需要一個存儲結構保存暫時不訪問的結點 存儲結構:堆棧、隊列
隊列實現:遍歷從根結點開始 首先將根結點入隊 然后開始執行循環:結點出隊、訪問該結點、其左右兒子入隊(注意隊列中先進先出原則)
序列特征:一層一層訪問的
步驟:
1.從隊列中取出一個元素;2.訪問該元素所指結點;3.若該元素所指結點的左右兒子結點非空 則將其左右兒子的指針順序入隊。
void LevelOrderTraversal( BinTree BT ){
Queue Q ; BinTree T ;
if ( !BT ) return ; //若是空樹直接返回
Q = CreateQueue ( MaxSize ) ; //創建并初始化Q
AddQ( Q, BT ) ;
while( ! IsEmptyQ ( Q ) ){
T = DeleteQ ( Q ) ;
printf ( “%d\n” , T -> Data ) ; //訪問取出隊列的結點
if ( T -> Left ) AddQ( Q, T -> Left );
if ( T -> Right ) AddQ( Q, T -> Right );
}
}
-遍歷二叉樹的應用:
eg:輸出二叉樹中的葉子結點,利用先序遍歷(中序后序類似)
void PreOrderTraversal ( BinTree BT )
{
if ( BT )
{
if( !BT -> Left && !BT -> Right )
printf ( “%d”, BT -> Data );
PreOrderTraversal ( BT -> Left );
PreOrderTraversal ( BT -> Right );
}
}
eg:求二叉樹的高度
void PostOrderGetHeight ( BinTree BT )
{ int HL, HR, MaxH ;
if ( BT )
{
HL = PostOrderGetHeight ( BT -> Left ); // 求左子樹的深度
HR = PostOrderGetHeight ( BT -> Right ); //求右子樹的深度
MaxH = ( HL > HR ) ? HL : HR ; //取左右子樹較大的深度
return ( MaxH + 1 ); //返回樹的深度
}
else return 0; // 空樹深度為0
}
eg:二元運算表達式樹及其遍歷:
先序遍歷得到前綴表達式:++a*b c*+*d e f g
中綴表達式會受到運算符優先級的影響,需要在遍歷時加括號
后序遍歷得到后綴表達式:a b c*+d e*f+g*+
eg:由兩種遍歷序列確定二叉樹
(必須知道中序二叉樹,若只是知道前序和后序遍歷 無法確定該二叉樹)
已知先序和中序遍歷序列 來確定一棵二叉樹
步驟:
根據先序遍歷序列第一個結點 確定根結點
根據根結點在中序遍歷序列中分割出左右兩個子序列
對左子樹和右子樹分別遞歸使用相同的方法繼續分解
practice:先序序列:a bcdefghij
中序序列:cbed a hgijf
由先序序列可知根結點為a,通過中序序列可知a左邊為左子樹 a右邊為右子樹,以此類推可確定二叉樹
類似地,已知后序和中序遍歷序列也可以確定一棵二叉樹