1. 程式人生 > >LeetCode145 二叉樹的後序遍歷(C++)

LeetCode145 二叉樹的後序遍歷(C++)

題目描述:

給定一個二叉樹,返回它的 後序 遍歷。

示例:

輸入: [1,null,2,3]  
   1
    \
     2
    /
   3 

輸出: [3,2,1]

進階: 遞迴演算法很簡單,你可以通過迭代演算法完成嗎?

 

資料結構定義:

struct TreeNode {
      int val;
      TreeNode *left;
      TreeNode *right;
      TreeNode(int x) : val(x), left(NULL), right(NULL) {}
 };

 

演算法思想:

/*一、遞迴
    效率較低,瞭解即可。
二叉樹的中序遍歷規則:
1. 遍歷左子樹;
2. 遍歷右子樹 
3. 訪問根結點;
*/

class Solution {
private:
    void rec(TreeNode* root,vector<int> &ret){
        if(root != NULL){            
            rec(root->left,ret);
            rec(root->right,ret);
            ret.push_back(root
->val); } } public: vector<int> postorderTraversal(TreeNode* root) { vector<int> ret; rec(root,ret); return ret; } };

 

/*
二、迭代
    效率較高,重點掌握。利用棧實現。對於節點p: 
1. p如果是葉子節點,直接輸出。 
2. p如果有孩子,且孩子沒有被訪問過,則按照右孩子,左孩子的順序依次入棧。(為了保證按照左孩子,右孩子的順序彈出)。 
3. p如果有孩子,而且孩子都已經訪問過,則訪問p節點。
為了分清返回的根節點時從左子樹還是右子樹返回的,增加輔助指標r,其指向最近訪問過的結點。

拓展:當訪問一個結點*p時,棧中結點恰好為*p結點的所有祖先。從棧底到棧底結點再加上*p結點,剛好構成從根節點到*p結點的一條路徑。這一特性非常重要,如求根結點到某結點的路徑;求兩個結點的最近公共祖先;均可用這個思想。
*/ class Solution { public: vector<int> postorderTraversal(TreeNode* root) { vector<int> ret; if(root == NULL) //特殊情況,為空樹 return ret; stack<TreeNode *> s; TreeNode *p = root; TreeNode *r = NULL; while(p||!s.empty()){ //結點不為空或棧中有元素 if(p){ //走到最左邊 s.push(p); p=p->left; } else{ //向右 p=s.top(); //取棧頂結點 if(p->right && p->right!=r){ //如果右子樹存在且未被訪問過,則入棧 p=p->right; s.push(p); p=p->left; //再走到最左 } else{ //否則,則彈出結點並訪問 s.pop(); //將結點彈出 ret.push_back(p->val); //訪問結點,存入向量中 r=p; //記錄最近訪問過的結點 p=NULL; //結點訪問完,重置p } } } return ret; } };

 

分析總結: