1. 程式人生 > 實用技巧 >007. 二叉樹的遍歷

007. 二叉樹的遍歷

------------------------------

  - 涉及內容:

  - 二叉樹的先中後序遍歷

  - 遞迴與非遞迴方式 , 虛擬碼實現

  - 2020/10/19

  - 應瞭解的內容:

  - 先中後序遍歷以根節點作為參照點,遍歷順序如下:

  - 先序:根左右

  - 中序:左根右

  - 後序:左右根

  - 畫圖最好理解

先序遍歷

-------------------------------------------------------------

-      引數說明:

-      T:根節點
-      lchild:左子樹
-      rchild:右子樹


-------------------------------------------------------------

遞迴:
      
void PreOrder(BiTree T) {

      if(T) {
      
            visit(T);
            PreOrder( T->lchild ) ;
            PreOrder( T->rchild ) ;
            
      }

}


非遞迴:需要藉助棧來實現

void PreOrder(BiTree T) {

      /* 
            初始化一個棧
            p指標指向頭節點
      */
      InitStack(s);      
      BiTree p = T;
      
      // 如果當前節點不空,或者棧不空,
      while( p || !IsEmpty(s) ) {      

            while( p ) {          
                  visit(p);      // 訪問節點,訪問次序,根左右
                  push(s,p);      
                  p = p->lchild;            
            }
            if( !IsEmpty(s) ) {
                  pop(s,p);
                  p = p->rchild;
            }
      }
}

中序遍歷

-------------------------------------------------------------

-      引數說明:

-      T:根節點
-      lchild:左子樹
-      rchild:右子樹


-------------------------------------------------------------

遞迴:
      
void InOrder(BiTree T) {

      if(T) {
      
            InOrder( T->lchild ) ;
            visit(T);
            InOrder( T->rchild ) ;
            
      }

}


非遞迴:需要藉助棧來實現

void InOrder(BiTree T) {

      /* 
            初始化一個棧
            p指標指向頭節點
      */
      InitStack(s);      
      BiTree p = T;
      
      // 如果當前節點不空,或者棧不空,
      while( p || !IsEmpty(s) ) {      

            if( p ) {          
                  push(s,p);      
                  p = p->lchild;            
            }
            else {
                  pop(s,p);
                  visit(T);            // 訪問節點,訪問次序:左根右
                  p = p->rchild;
            }
      }
}

後序遍歷

-------------------------------------------------------------

-      引數說明:

-      T:根節點
-      lchild:左子樹
-      rchild:右子樹


-------------------------------------------------------------

遞迴:
      
void PostOrder(BiTree T) {

      if(T) {
            PostOrder( T->lchild ) ;
            PostOrder( T->rchild ) ;
            visit(T);
      }
}


非遞迴:非遞迴後序遍歷的節點要兩次入棧,兩次出棧


struct element{
      BiTree *ptr;
      int flag;      // flag表示入棧的次數
}elem;

void PostOrder(BiTree T) {

      /* 
            初始化一個棧
            p指標指向頭節點
      */
      InitStack(s);      
      BiTree p = T;
      
      // 如果當前節點不空,或者棧不空,
      while( p || !IsEmpty(s) ) {      

            if( p ) {                                                         //      L1
                  elem.ptr = p;
                  elem.flag = 1;      
                  push(s,elem);    // 將指標地址以及入棧次數儲存到棧中
                  p = p->lchild;            
            }
            else {
                  elem = push(s,elem);
                  p = elem.ptr;
                  
                  if(elem.flag == 1) {
                        elem.flag = 2;
                        push(s,elem);
                        p = p->rchild;
                  }
                  
                  else {
                        visit(p);
                        p = NULL;      // 訪問節點之後,p置為空指標,確保下次迴圈時可以直接跳過L1語句,也就是第一個if語句
                  }
            }
      }
}