1. 程式人生 > >二叉樹的深度優先遍歷(棧)和廣度優先遍歷(佇列)

二叉樹的深度優先遍歷(棧)和廣度優先遍歷(佇列)

前序,中序和後序遍歷都是深度優先遍歷的特例 :所以直接先序中序後續遍歷也可以

深度優先遍歷棧,先壓右節點,再壓左節點

也就深入的遍歷,沿著每一個分支直到走到最後,然後才返回來遍歷剩餘的節點。二叉樹不同於圖,圖需要標記節點是否已經訪問過,因為可能會存在環,而二叉樹不會出現環,所以不需要標記。那麼,我們只需要一個棧空間,來壓棧就好了。因為深度優先遍歷,遍歷了根節點後,就開始遍歷左子樹,所以右子樹肯定最後遍歷。我們利用棧的性質,先將右子樹壓棧,然後在對左子樹壓棧。此時,左子樹節點是在top上的,所以可以先去遍歷左子樹。

如下是深度優先遍歷的程式碼:

  1. void DepthFirstTravel(Tree *root)  
  2. {  
  3.     stack<Tree *> s;  
  4.     s.push(root);  
  5.     while(!s.empty())  
  6.     {  
  7.         root = s.top();  
  8.         cout << root->data << " ";  
  9.         s.pop();  
  10.         if(root->rchild != NULL)  
  11.         {  
  12.             s.push(root->rchild);  
  13.         }  
  14.         if(root->lchild != NULL)  
  15.         {  
  16.             s.push(root->lchild);  
  17.         }  
  18.     }  
  19. }  

廣度優先遍歷二叉樹(佇列:先壓左節點,再壓右節點)

也就是按層次的去遍歷。依次遍歷根節點,然後是左孩子和右孩子。所以要遍歷完當前節點的所有孩子,這樣才是層次遍歷嘛。此時我們就不能用棧這個資料結構了,因為棧只能在棧頂操作。在這裡,我們需要根據左右孩子的順序來輸出,所以就是先進先出的原則,那麼我們當然就想到了佇列這個資料結構。可以在rear依次插入左右孩子,在front依次讀取並刪除左右孩子,這樣就保證了層次的輸出。

下面是二叉樹的廣度優先遍歷程式碼:

  1. void BreadthFirstTravel(Tree *root)  
  2. {  
  3.     queue<Tree *> q;  
  4.     q.push(root);  
  5.     while(!q.empty())  
  6.     {  
  7.         root = q.front();  
  8.         cout << root->data << " ";  
  9.         q.pop();  
  10.         if(root->lchild != NULL)  
  11.         {  
  12.             q.push(root->lchild);  
  13.         }  
  14.         if(root->rchild != NULL)  
  15.         {  
  16.             q.push(root->rchild);  
  17.         }  
  18.     }  
  19. }