數據結構:二叉樹遍歷及其堆棧實現和應用


二叉樹的非遞歸遍歷

  • 使用堆棧

中序

  • 遇到一個結點,就把它壓棧,並去遍歷它的左子樹;
  • 當左子樹遍歷結束后,從棧頂彈出這個結點並訪問它;
  • 然后按其右指針再去中序遍歷該結點的右子樹。
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 */
}

先序和中序遍歷序列來確定一棵二叉樹

  • 根據先序遍歷序列第一個結點確定根結點
  • 根據根結點在中序遍歷序列中分割出左右兩個子序列
  • 對左子樹和右子樹分別遞歸使用相同的方法繼續分解。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM