二叉樹后序遍歷非遞歸的三種寫法 (數據結構)


樹結點結構體:

1 /**
2  * Definition for a binary tree node.
3  * struct TreeNode {
4  *     int val;
5  *     TreeNode *left;
6  *     TreeNode *right;
7  *     TreeNode(int x) : val(x), left(NULL), right(NULL) {}
8  * };
9  */

因為在后序遍歷中,要保證左孩子和右孩子都已被訪問並且左孩子在右孩子前訪問才能訪問根結點

第一種: 對於任一結點P,將其入棧,然后沿其左子樹一直往下搜索,直到搜索到沒有左孩子的結點,此時該結點出現在棧頂,但是此時不能將其出棧並訪問,因此其右孩子還為被訪問。所以接下來按照相同的規則對其右子樹進行相同的處理,當訪問完其右孩子時,該結點又出現在棧頂,此時可以將其出棧並訪問。這樣就保證了正確的訪問順序。可以看出,在這個過程中,每個結點都兩次出現在棧頂,只有在第二次出現在棧頂時,才能訪問它。因此需要多設置一個變量標識該結點是否是第一次出現在棧頂。

前中序非遞歸遍歷的方法: 不斷搜左子樹,然后出棧,指向右子樹,如此循環。

 1    vector<int> postorderTraversal(TreeNode* root) {
 2         vector<int> result;
 3         if (root==nullptr) return result;
 4         TreeNode * mark = NULL;  // 標記變量
 5         stack<TreeNode *> S;
 6         S.push(root);
 7         root = root->left;
 8         
 9         while (!S.empty())
10         {
11             while (root)
12             {
13                 S.push(root);
14                 root = root->left;
15             }
16             mark = NULL;
17             while (!S.empty()) // 如果是右子樹返回,所以要循環
18             {
19                 root = S.top();
20                 S.pop();
21 
22                 if (root->right == mark)  // 從右子樹返回
23                 {
24                     result.push_back(root->val);
25                     mark = root;
26                 }
27                 else   // 從左子樹返回
28                 {
29                     S.push(root);
30                     root = root->right;
31                     break;
32                 }
33             }
34 
35         } 
36         return result;
37     }

第二種:要保證根結點在左孩子和右孩子訪問之后才能訪問,因此對於任一結點P,先將其入棧。如果P不存在左孩子和右孩子,則可以直接訪問它;或者P存在左孩子或者右孩子,但是其左孩子和右孩子都已被訪問過了,則同樣可以直接訪問該結點。若非上述兩種情況,則將P的右孩子和左孩子依次入棧,這樣就保證了每次取棧頂元素的時候,左孩子在右孩子前面被訪問,左孩子和右孩子都在根結點前面被訪問。

 1 vector<int> postorderTraversal(TreeNode *root)     //非遞歸后序遍歷
 2 {
 3     vector<int> result;
 4     if(root == nullptr)
 5         return result;
 6     stack<TreeNode *> s;
 7     TreeNode *cur;                      //當前結點 
 8     TreeNode *pre = nullptr;            //前一次訪問的結點 
 9     s.push(root);
10     while(!s.empty())
11     {
12         cur=s.top();
13         if((cur->left==nullptr&&cur->right==nullptr)||
14            (pre!=nullptr&&(pre==cur->left||pre==cur->right)))
15         {
16             result.push_back(cur->val);  //如果當前結點沒有孩子結點或者孩子節點都已被訪問過 
17             s.pop();
18             pre=cur;
19         }
20         else
21         {
22             if(cur->right != nullptr)
23                 s.push(cur->right);
24             if(cur->left != nullptr)
25                 s.push(cur->left);
26         }
27     }
28     return result;
29 }

 

第三種:

前序遍歷:根-左子樹-右子樹

后序遍歷:左子樹-右子樹-根 把前序遍歷倒過來:右子樹-左子樹-根 !左右子樹相反,不能直接倒!

先左子樹入棧,在右子樹入棧 (和前序遍歷相反,也就是顛倒了左右子樹->根-右子樹-左子樹),最后輸出顛倒一下即可!

 1 class Solution:
 2     # @param root, a tree node
 3     # @return a list of integers
 4     def postorderTraversal(self, root):
 5         if not root: return []
 6         ans,q=[],[]
 7         q.append(root)
 8         while q:
 9             cur=q.pop()          
10             if cur.left: q.append(cur.left)
11             if cur.right: q.append(cur.right)
12             ans.append(cur.val)
13         return ans[::-1]

 

參考自:http://www.cnblogs.com/dolphin0520/archive/2011/08/25/2153720.html


免責聲明!

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



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