二叉树的前序、中序、后序遍历非递归
二叉树的前序递归、中序递归、后序递归不说了,是人都会写。
前序非递归:
前序是中-》左-》右,那么对于当前节点cur来说,我们要先把cur的值放入结果数组。再深入其左子树。左子树遍历完后,再深入其右子树。
那么显然再我们深入其左子树前,需要保存当前节点cur,因为之后还要遍历cur的右子树。
/** * Definition for a binary tree node. * struct TreeNode { * int val; * TreeNode *left; * TreeNode *right; * TreeNode(int x) : val(x), left(NULL), right(NULL) {} * }; */ class Solution { public: vector<int> preorderTraversal(TreeNode* root) { stack<TreeNode*> sta; vector<int> res; auto cur=root; while(cur or not sta.empty()){ if(cur==nullptr){ cur=sta.top()->right; sta.pop(); } else{ res.emplace_back(cur->val); sta.push(cur); cur=cur->left; } } return res; } };
中序非递归:
和前序都差不多的,只不过顺序改为:左-》中-》右。
/** * Definition for a binary tree node. * struct TreeNode { * int val; * TreeNode *left; * TreeNode *right; * TreeNode(int x) : val(x), left(NULL), right(NULL) {} * }; */ class Solution { public: vector<int> inorderTraversal(TreeNode* root) { stack<TreeNode*> sta; vector<int> res; auto cur=root; while(cur or not sta.empty()){ if(cur==nullptr){ res.emplace_back(sta.top()->val); cur=sta.top()->right; sta.pop(); } else{ sta.push(cur); cur=cur->left; } } return res; } };
后序非递归:
这个有点难度,因为什么呢,后序顺序是:左-》右-》中。所以对于一个节点cur,我们先遍历其左子树,那首先要把cur入栈,对吧?然后我们还要遍历cur的右子树。最后再遍历cur。
问题就是遍历完左子树后,我们会回去找cur(为了找cur的右子树)。
遍历完右子树后,也会回去找cur(为了遍历cur本身,因为左-》右-》中嘛)。
那如何区别这两种情况呢?
可以使用一个bool变量用来指示我们是否遍历完当前节点的子树:
struct point{ TreeNode* node; bool FinishSubtree; point(TreeNode* x){ node=x; FinishSubtree=false;//该值为false,说明还没有遍历完左右子树。为true则表示遍历完了左右子树 } point():node(nullptr),FinishSubtree(false){} };
如上面注释所说,对于一个节点cur,我们先入栈cur。然后遍历其左子树,此时cur对应的标记应该是false,因为还没有遍历右子树。
等我们遍历完cur的左子树后,回来找cur的右子树时,我们把cur的标记置为true,表明这个cur节点的子树已经被遍历完了(虽然此时右子树还没遍历,但我们接下来第一步会先遍历其右子树,再回来找cur,这个时候cur的左右子树确实已经被遍历完了)。这样我们遍历好cur的右子树后,回来再输出cur的val。这样正好满足左-》右-》中的顺序。最终我们终于可以pop掉cur了,因为cur及其左右子树都遍历完毕了。
/** * Definition for a binary tree node. * struct TreeNode { * int val; * TreeNode *left; * TreeNode *right; * TreeNode(int x) : val(x), left(NULL), right(NULL) {} * }; */ class Solution { public: struct point{ TreeNode* node; bool FinishSubtree; point(TreeNode* x){ node=x; FinishSubtree=false;//该值为false,说明还没有遍历完左右子树。为true则表示遍历完了左右子树 } point():node(nullptr),FinishSubtree(false){} }; vector<int> postorderTraversal(TreeNode* root) { stack<point> sta; vector<int> res; TreeNode* cur=root; point p; while(cur or not sta.empty()){ if(cur==nullptr){ p=sta.top(); if(p.FinishSubtree==false){//左子树完成 sta.top().FinishSubtree=true; //更新标记为true,这样等右子树遍历完后,堆顶的左右子树就都遍历完了,堆顶可以直接pop cur=p.node->right; } else{ res.emplace_back(sta.top().node->val); sta.pop(); } } else{ sta.push(point(cur)); cur=cur->left; } } return res; } };
进击的小🐴农

浙公网安备 33010602011771号