二叉樹的非遞歸遍歷-----2013年3月20日

      二叉樹的遞歸遍歷算法非常漂亮和易讀,但是非遞歸算法就沒那麼容易懂了,尤其是後序遍歷的非遞歸算法。

一. 前序遍歷

      
複製代碼
 1 void PreOrderTraverse(Node *root)
 2 {
 3     stack<Node *> ns;
 4     Node *n=root;
 5     while(n!=NULL || !ns.empty())
 6     {
 7         if(n!=NULL) 
 8         {
 9             print(n); 
10             ns.push(n);
11             n=n->pLeft;
12         }
13         else
14         {
15             ns.pop(n); 
16             n=n->pRight;
17         }
18     }
19 }
複製代碼

二.中序遍歷

      
複製代碼
 1 void InOrderTraverse(Node *root)
 2 {
 3     stack<Node *> ns;
 4     Node *n=root;
 5     while(n!=NULL || !ns.empty())
 6     {
 7         if(T!=NULL) 
 8         {
 9             ns.push(n); 
10             n=n->pLeft;
11         }
12         else
13         {
14             ns.pop(n); 
15             print(n);
16             n=n->pRight;
17         }
18     }
19 }
複製代碼

三. 後序遍歷

       後序遍歷就比較麻煩了,有兩種算法。後序遍歷的關鍵是保證兒子結點先於父結點打印。
      第一種:還是跟先序和中序一樣,一路往左走,找到最左的一個結點A。A不可能再有左兒子了,但可能有右兒子。而這是A第一次爲stack的top結點,但是這時還不能打印它。將A的右兒子入棧後,再次執行,待到A第二次成爲top時,這說明A右兒子結點已經處理了,因爲A結點在棧中的位置必然是在右兒子之下的。用一個變量來表示這個二次的關係。代碼如下:
複製代碼
 1 void PostOrderTraverse(Node *root)
 2 {
 3     stack<Node *> ns;
 4     Node *n=root;
 5     while(n!=NULL || !ns.empty())
 6     {
 7         if(n!=NULL)        
 8         {
 9             n->IsFirst=true;//The first time to be the top of ns stack.
10             ns.push(n);
11             n=n->pLeft;
12         }
13         else
14         {
15             if(!ns.empty()) 
16             {
17                 ns.pop(n); 
18                 if(n->IsFirst==true)//The first time to be the top of ns stack.Don't print.
19                 {
20                     n->IsFirst=false;
21                     ns.push(n); 
22                     n=n->pRight;
23                 }
24                 else  //The second time.Print it.
25                     print(n); 
26             }
27         }
28     }
29 }
複製代碼
 
      第二種思路:後序遍歷的順序是:左兒子->右兒子->父結點。那麼,入棧的順序就應該倒過來,即:父結點->右兒子->左兒子。當前top位置的結點如果沒有左右兒子結點或者是左右兒子結點都已經訪問過了,那麼就可以打印出來;如果不是這樣,就將右兒子和左兒子依次入棧。注意,這裏需要保存當前top位置之前的那次訪問的結點,而且root結點需要在while循環之前入棧。代碼如下:
複製代碼
 1 void PostOrderTraverse2(Node *root)
 2 {
 3     stack<Node *> ns;
 4     Node *n=root;
 5     Node *previous=NULL;//It is NULL at first.
 6     ns.push(n);
 7     while(n!=NULL || !ns.empty())
 8     {
 9         n=ns.top(); 
10         if( (n->pLeft==NULL && n->pRight==NULL) || (previous==n->pLeft || previous==n->pRight))
11         {
12             print(n); 
13             ns.pop();
14             previous=n;
15         }
16         else
17         {
18             if(n->pRight!=NULL)
19                 ns.push(n->pRight);   
20             if(n->pLeft!=NULL)
21                 ns.push(n->pLeft);   
22         }
23     }
24 }
複製代碼
 
       參考資料:http://www.cnblogs.com/dolphin0520/archive/2011/08/25/2153720.html
      如果你覺得我的文章對你有幫助,請贊一下,非常感謝!
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章