二叉樹的非遞歸遍歷
- 使用堆棧
中序
- 遇到一個結點,就把它壓棧,並去遍歷它的左子樹;
- 當左子樹遍歷結束后,從棧頂彈出這個結點並訪問它;
- 然后按其右指針再去中序遍歷該結點的右子樹。
void InOrderTraversal( BinTree BT )
{ BinTree T=BT;
Stack S = CreatStack( MaxSize ); /*創建並初始化堆棧S*/
while( T || !IsEmpty(S) ){
while(T){ /*一直向左並將沿途結點壓入堆棧*/
Push(S,T);
T = T->Left;
}
if(!IsEmpty(S)){
T = Pop(S); /*結點彈出堆棧*/
printf(“%5d”, T->Data); /*(訪問)打印結點*/
T = T->Right; /*轉向右子樹*/
}
}
}
先序
void InOrderTraversal( BinTree BT )
{ BinTree T BT;
Stack S = CreatStack( MaxSize ); /*創建並初始化堆棧S*/
while( T || !IsEmpty(S) ){
while(T){ /*一直向左並將沿途結點壓入堆棧*/
Push(S,T);
T = T->Left;
}
if(!IsEmpty(S)){
T = Pop(S); /*結點彈出堆棧*/
printf(“%5d”, T->Data); /*(訪問)打印結點*/
T = T->Right; /*轉向右子樹*/
}
}
}
層序遍歷
-
核心問題: 二維結構的線性化,二維到一維
-
問題:會丟失父結點
-
需要一個存儲結構保存暫時不訪問的結點,比如堆棧、隊列。
-
隊列實現:遍歷從根結點開始,首先將根結點入隊,然后開始執行循環:結點出隊、訪問該結點、其左右兒子入隊
層序基本過程
- 從隊列中取出一個元素;
- 訪問該元素所指結點;
- 若該元素所指結點的左、右孩子結點非空, 則將其左、右孩子的指針順序入隊。
代碼實現
void LevelOrderTraversal ( BinTree BT )
{ Queue Q; BinTree T;
if ( !BT ) return; /* 若是空樹則直接返回 */
Q = CreatQueue( 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 );
}
}
遍歷二叉樹的應用
輸出二叉樹的葉結點
- 在二叉樹的遍歷算法中增加檢測結點的“左右子樹是否都為空”。
void PreOrderPrintLeaves( BinTree BT )
{
if( BT ) {
if ( !BT-Left && !BT->Right )
printf(“%d”, BT->Data );
PreOrderPrintLeaves ( BT->Left );
PreOrderPrintLeaves ( BT->Right );
}
}
求二叉樹的高度
int 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 */
}
先序和中序遍歷序列來確定一棵二叉樹
- 根據先序遍歷序列第一個結點確定根結點;
- 根據根結點在中序遍歷序列中分割出左右兩個子序列
- 對左子樹和右子樹分別遞歸使用相同的方法繼續分解。