二叉樹遍歷算法

二叉樹遍歷算法包含: 前序, 中序, 後序, 層次遍歷 共四種算法。算法

先序遍歷 DLR: 先訪問根節點,而後訪問左子樹, 最後訪問右子樹post

中序遍歷LDR: 先訪問左子樹,而後根節點,最後訪問右子樹遞歸

後序遍歷LRD: 先訪問左子樹,而後訪問右子樹,最後根節點隊列

層次遍歷: 從每層開始,至左向右逐層訪問it

 

先序、中序,後序均可以使用遞歸方式進行訪問,非遞歸方式使用棧輔助,  層次遍歷使用隊列做爲輔助結構二叉樹

 

1. 先序非遞歸遍歷算法:遍歷

每次遞歸深刻的時候,就是將左右孩子節點壓棧的過程,在壓棧以前,訪問該節點;top

每一個節點只有在訪問完右子樹,或者右子樹爲空時,出棧,爲了標誌每一個節點的右孩子節點是否壓棧,能夠使用一個標誌位flag,將節點的右孩子節點壓入棧中,須要改變flag,這樣每次訪問棧頂元素時,若是判斷右子樹已訪問,直接出棧;vi

 詳細算法以下:while

最開始根節點入棧

while(棧非空){

1. 獲取棧頂元素cur;

2. 判斷該節點的flag, 若是flag爲true,說明該節點右子樹已經訪問,出棧, 不然 訪問該節點cur;

3. 若是cur有左孩子節點,壓入棧中,進入step 1;

不然,若是有右孩子節點(只有右子樹),壓入棧中,同時修改cur的標誌位flag爲true;若是cur爲葉子節點,直接出棧,進入step1

}

 

void preOrder(BitNode *t){

if(!t) return;

Stack<BitNode*> s;

s.push(t);

BitNode *cur=NULL;

while( !s.empty() ){

cur= s.top();

if(cur.flag){

//右子樹已經訪問,出棧

s.pop();

}else{

visit(cur); //訪問該節點

if(cur->lchild){

s.push(cur->lchild);//訪問左子樹

}else{

if(cur->rchild){//訪問右子樹

s.push(cur->rchild);

cur->flag= true;

}else{

//葉子節點

s.pop();

}

}

}

}

}

 

2. 中序遍歷非遞歸算法:

與先序遍歷相似,只是訪問完左子樹後訪問根節點,訪問完根節點,出棧,最後訪問完右子樹,爲了標誌每一個節點的左子樹是否訪問,使用標誌位flag

 詳細算法以下:

最開始根節點入棧

while(棧非空){

1. 獲取棧頂元素cur;

2. 若是cur節點標誌位爲flag爲false, 且該節點有左子樹,將左子樹壓入棧中,同時置該節點標誌位flag爲true;不然訪問該節點,並出棧,若是該節點有右子樹,將右孩子壓入棧中

}

void inOrder(BitNode *t){

  if(!t) return;

      Stack<BitNode*> s;

      s.push(t);

      BitNode* cur=NULL;

      while( !s.empty() ){

    cur = s.top();

             if(cur->flag){

    visit(cur);

              s.pop();

            if(cur->rchild){

    s.push(cur->rchild);

    }

  }

   }//while         

}

}

 

3. 後序遍歷二叉樹非遞歸算法:

先訪問左右子樹,最後訪問根節點,一樣的,若是該節點的左右子樹都已訪問,直接出棧,不然更新節點的訪問左右子樹狀態,若是狀態爲右子樹已經訪問,直接出棧

 

詳細算法以下:

最開始根節點入棧

while(棧非空){

1. 獲取棧頂元素cur;

2. 若是cur節點標誌位爲flag爲2, 右子樹已經訪問完,訪問該節點出棧, 不然,

 若是flag==1, 代表該節點左子樹已經訪問,開始訪問右子樹,若是該節點無右子樹,訪問該節點後直接出棧 不然,將右孩子壓入棧中,同時置該節點標誌位flag爲2

 若是flag==0,代表該節點左右子樹均未訪問, 先訪問左子樹,若是該節點有左子樹,將左子樹壓入棧中,同時置該節點標誌位flag爲1,代表左子樹已經訪問完, 不然判斷若是該節點有右子樹,將右孩子壓入棧中,同時置該節點標誌位flag爲2,不然該節點爲葉子節點,訪問該節點後直接出棧

}

void postOrder(BitNode *t){

  if(!t) return;

      Stack<BitNode*> s;

      s.push(t);

      BitNode* cur=NULL;

      while( !s.empty() ){

    cur = s.top();

             if(cur->flag==2){

    visit(cur);

              s.pop();

           }else if(cur-> flag==0 ){

         if(cur->lchild){

          s.push(cur->lchild);

         cur->flag =1;

        }else{

      if(cur->rchild){

    s.push(cur->rchild);

              cur->flag=2;

    }else{

               //葉子節點

      visit(cur);

              s.pop();

            }

     }   

  }

   }//while         

}

 

4.層次遍歷算法:

使用隊列FIFO的特性,至左向右依次將根節點的孩子節點壓入隊列中

相關文章
相關標籤/搜索