LeetCode 144, 94, 145. Binary Tree Preorder/Inorder/Postorder Traversal
递归非常好写,这里主要记录非递归的写法。
Preorder
方法一:直接利用栈来写。
class Solution { public: vector<int> preorderTraversal(TreeNode* root) { if (root==NULL) return vector<int>(); stack<TreeNode *> s({root}); vector<int> res; while (!s.empty()){ TreeNode *cur=s.top(); s.pop(); res.push_back(cur->val); if (cur->right) s.push(cur->right); if (cur->left) s.push(cur->left); } return res; } };
方法二:先左子树一路访问下去,全部访问完毕回溯并访问右边。p = s.top() 代表 p 的左子树已经全部访问完毕,p=s.top() 回到 p 结点,接着访问右子树。
除了这种 if else 写法,while(p){s.push(p); p=p->next} 然后接 p=s.top(); s.pop(); p=p->right; 也是可以的,思路更清楚。
class Solution { public: vector<int> preorderTraversal(TreeNode* root) { vector<int> res; stack<TreeNode *> s; TreeNode *p=root; while (!s.empty() || p!=NULL){ if (p!=NULL){ s.push(p); res.push_back(p->val); p = p->left; }else{ p = s.top(); s.pop(); p = p->right; } } return res; } };
Inorder
方法一:和Preorder方法一类似,直接做,但是需要一个计数器,第二次出栈的时候才可以输出。
class Solution { public: vector<int> inorderTraversal(TreeNode* root) { vector<int> res; if (root==NULL) return res; unordered_map<TreeNode *,int> hash; //default value is 0; stack<TreeNode *> s({root}); while (!s.empty()){ TreeNode *cur=s.top(); s.pop(); if (hash[cur]==0){ ++hash[cur]; s.push(cur); if(cur->left) s.push(cur->left); }else{ res.push_back(cur->val); if(cur->right) s.push(cur->right); } } return res; } };
方法二:和Preorder方法二相同,只是push_back到结果的时机不同:再访问完左子树以后再添加。
class Solution { public: vector<int> inorderTraversal(TreeNode* root) { vector<int> res; stack<TreeNode *> s; TreeNode *p=root; while (!s.empty() || p!=NULL){ if (p!=NULL){ s.push(p); p = p->left; }else{ p = s.top(); s.pop(); res.push_back(p->val); p = p->right; } } return res; } };
Postorder
方法一:同上
class Solution { public: vector<int> postorderTraversal(TreeNode* root) { vector<int> res; if (root==NULL) return res; unordered_map<TreeNode *,int> hash; //default value is 0; stack<TreeNode *> s({root}); while (!s.empty()){ TreeNode *cur=s.top(); s.pop(); if (hash[cur]==0){ ++hash[cur]; s.push(cur); if(cur->left) s.push(cur->left); }else if (hash[cur]==1){ ++hash[cur]; s.push(cur); if(cur->right) s.push(cur->right); }else{ res.push_back(cur->val); } } return res; } };
方法二:后序遍历顺序是 左右根,反过来是 根右左,而 根右左 和 前序遍历很类似,因此把 根右左 做出来,答案reverse一下就好。
由于前序遍历有两种方法,因此这里也可以两种方法来写。
class Solution { public: vector<int> postorderTraversal(TreeNode* root) { vector<int> res; if (root==NULL) return res; stack<TreeNode *> s({root}); while (!s.empty()){ TreeNode *cur=s.top(); s.pop(); res.push_back(cur->val); if (cur->left) s.push(cur->left); if (cur->right) s.push(cur->right); } reverse(res.begin(),res.end()); return res; } };
class Solution { public: vector<int> postorderTraversal(TreeNode* root) { vector<int> res; stack<TreeNode *> s; TreeNode *p=root; while (!s.empty() || p!=NULL){ if (p!=NULL){ s.push(p); res.push_back(p->val); p = p->right; }else{ p = s.top(); s.pop(); p = p->left; } } reverse(res.begin(),res.end()); return res; } };
结点个数为n的话,时间复杂度为 O(n)。
空间复杂度如果只用栈,平均为树的高度,即 O(logn) ,最坏情况 O(n) 。

浙公网安备 33010602011771号