三种遍历:
- 先序:根 左 右
- 中序:左 根 右
- 后续:左 右 根
先看一种我认为比较秒的方法
vector<int> postorderTraversal(TreeNode* root) { if(root == NULL) return vector<int>{}; vector<int>res; stack<TreeNode*>st; st.push(root); while(!st.empty()) { TreeNode* p = st.top();st.pop(); res.push_back(p->val); if(p->left) st.push(p->left); // 先左 if(p->right) st.push(p->right); // 后右,这样弹出时才能先右后左 } reverse(res.begin(), res.end()); return res; }
如果是先序遍历,只需改成先右后左;
但是这种方法不能实现中序遍历。
另外的思路是对访问过的节点进行标记,可以只标记最后一个被pop的
1、使用一个栈,先把二叉树的右孩子压入,再把左孩子压入。这样在输出时就满足后序要求(先左后右)。
2、当某个节点的左孩子或者右孩子都为NULL时,可以访问。此外记录当前节点p的上一个节点last,因为当p的左右孩子都已访问过时,轮到p被访问,设置last可标志p的左右孩子是否都被访问过了。即为 if((p->right == NULL && p->left == last) || p->right == last)
vector<int> postorderTraversal(TreeNode* root) { if(root == NULL) return vector<int>{}; vector<int>res; stack<TreeNode*>st; st.push(root); TreeNode* pre; // 记录上一个pop的节点 while(!st.empty()) { TreeNode* p = st.top(); if((p->left == NULL && p->right == NULL) || (p->left == pre && p->right == NULL) || (p->right == pre)) { res.push_back(p->val); pre = p; st.pop(); } else { if(p->right) st.push(p->right); if(p->left) st.push(p->left); } } return res; }
或者用unordered_map进行标记,
一种统一的写法:
二叉树的遍历都可以借助栈结构使用DFS算法完成。
首先是最简单的先序遍历,父>左>右。见144题 。
每次入栈前先将父节点加入结果列表,然后左节点入栈。
当左子树遍历完后,再遍历右子树。
class Solution: def preorderTraversal(self, root: TreeNode) -> List[int]: res = [] #结果列表 stack = [] #辅助栈 cur = root #当前节点 while stack or cur: while cur: #遍历到最后一层 res.append(cur.val) stack.append(cur) cur = cur.left top = stack.pop() #此时该节点的左子树已经全部遍历完 cur = top.right #对右子树遍历 return res
接着来看后序遍历,左>右>父。见145题 。
能不能借助先序遍历的思路来呢,我们将上面的顺序翻转过来得到,父>右>左。
所以现在可以按照之前的方法遍历,最后把结果翻转一下。
class Solution: def postorderTraversal(self, root: TreeNode) -> List[int]: res = [] stack = [] cur = root while stack or cur: while cur: res.append(cur.val) stack.append(cur) cur = cur.right #先将右节点压栈 top = stack.pop() #此时该节点的右子树已经全部遍历完 cur = top.left #对左子树遍历 return res[::-1] #结果翻转
最后来看下中序遍历, 左>父>右。见94题 。
与先序遍历不同的是,出栈时才将结果写入列表。
class Solution: def inorderTraversal(self, root: TreeNode) -> List[int]: res = [] stack = [] cur = root while stack or cur: while cur: stack.append(cur) cur = cur.left top = stack.pop() #此时左子树遍历完成 res.append(top.val) #将父节点加入列表 cur = top.right #遍历右子树 return res
参考链接:
1. https://blog.csdn.net/exceptional_derek/article/details/17551459