LeetCode145 二叉樹的後序遍歷(C++)
阿新 • • 發佈:2018-11-07
題目描述:
給定一個二叉樹,返回它的 後序 遍歷。
示例:
輸入: [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; } };
分析總結: