145. 二叉树的后序遍历
文章目录
一、题目
给你一棵二叉树的根节点 root ,返回其节点值的 后序遍历 。
示例 1:

输入:root = [1,null,2,3]
输出:[3,2,1]
示例 2:
输入:root = []
输出:[]
示例 3:
输入:root = [1]
输出:[1]
提示:
- 树中节点的数目在范围
[0, 100]内 -100 <= Node.val <= 100
**进阶:**递归算法很简单,你可以通过迭代算法完成吗?
二、思路及代码
方法一:递归(比较简单)
/**
* Definition for a binary tree node.
* struct TreeNode {
* int val;
* TreeNode *left;
* TreeNode *right;
* TreeNode() : val(0), left(nullptr), right(nullptr) {}
* TreeNode(int x) : val(x), left(nullptr), right(nullptr) {}
* TreeNode(int x, TreeNode *left, TreeNode *right) : val(x), left(left), right(right) {}
* };
*/
class Solution {
public:
vector<int> v;
vector<int> postorderTraversal(TreeNode* root) {
if(root!=NULL){
postorderTraversal(root->left);
postorderTraversal(root->right);
v.push_back(root->val);
}
return v;
}
};
方法二:迭代(两种方法)
版本一
算法思路:
后序遍历的顺序是左子树、右子树、根节点。要实现后序遍历,可以使用栈的结构进行辅助。
-
初始化一个空栈和结果数组
-
将根节点入栈,并向左子树遍历
-
当左边遍历到头时,从栈顶取出节点,判断其右子树是否遍历过
3.1 如果右子树未遍历,则将右子树作为根节点,向右子树遍历
3.2 如果右子树已遍历或为空,则将这个节点放入结果数组中
-
重复上述操作,直到栈空为止
这样就可以通过栈的结构实现后序遍历的顺序。
具体实现:
-
定义栈和结果数组
-
当根节点或栈非空时循环
2.1 将根节点入栈,遍历左子树
2.2 从栈顶取出节点temp,判断其右子树
2.3 如果右子树未遍历,则遍历右子树
2.4 如果右子树已遍历,则将temp节点的值放入结果数组
-
返回结果数组
通过栈保存节点的顺序,模拟后序遍历的过程,从而实现后序遍历二叉树。
/**
* Definition for a binary tree node.
* struct TreeNode {
* int val;
* TreeNode *left;
* TreeNode *right;
* TreeNode() : val(0), left(nullptr), right(nullptr) {}
* TreeNode(int x) : val(x), left(nullptr), right(nullptr) {}
* TreeNode(int x, TreeNode *left, TreeNode *right) : val(x), left(left), right(right) {}
* };
*/
class Solution {
public:
vector<int> postorderTraversal(TreeNode* root) {
stack<TreeNode*> st;
vector<int> result;
TreeNode *prev = nullptr;
while(root != NULL || !st.empty()){
if(root != NULL){
st.push(root);
root = root->left;
}
else{
TreeNode* temp = st.top();
if(temp->right != NULL && temp->right != prev){
root = temp->right;
}else{
result.push_back(temp->val);
st.pop();
prev = temp;
}
}
}
return result;
}
};
算法分析:
- 时间复杂度O(n):需要遍历所有节点
- 空间复杂度O(n):栈的大小最大为n
版本2
算法思路:
这种方法的核心思路是,将前序遍历“根节点、左子树、右子树”的顺序改变为“根节点、右子树、左子树”,然后对结果反转,就可以得到后序遍历的顺序“左子树、右子树、根节点”。
具体来说:
-
初始化栈和结果数组
-
将根节点入栈
-
当栈非空时循环:
3.1 从栈顶弹出节点p
3.2 将p的值放入结果数组
3.3 先将p的右子树入栈
3.4 再将p的左子树入栈
-
反转结果数组
-
返回结果数组
通过修改前序遍历的顺序,并倒置结果,达到后序遍历的效果。
/**
* Definition for a binary tree node.
* struct TreeNode {
* int val;
* TreeNode *left;
* TreeNode *right;
* TreeNode() : val(0), left(nullptr), right(nullptr) {}
* TreeNode(int x) : val(x), left(nullptr), right(nullptr) {}
* TreeNode(int x, TreeNode *left, TreeNode *right) : val(x), left(left), right(right) {}
* };
*/
//本方法是前序遍历的变体,前序遍历是中左右,我们转换为中右左,最终倒序以后成为左右中
class Solution {
public:
vector<int> postorderTraversal(TreeNode* root) {
vector<int> v;
stack<TreeNode*>st;
if(root==NULL){
return v;
}
st.push(root);
while(!st.empty()){
TreeNode *p = st.top();
st.pop();
v.push_back(p->val);
if(p->left) st.push(p->left);
if(p->right) st.push(p->right);
}
reverse(v.begin(),v.end());//倒序
return v;
}
};
算法分析:
- 时间复杂度 O(n):需要遍历所有节点
- 空间复杂度 O(n):栈的大小最大为 n
本文介绍了如何对二叉树进行后序遍历,提供了递归和两种迭代方法的详细代码实现。递归方法直观简单,而迭代方法利用栈结构模拟递归过程,确保了正确顺序。两种迭代方法分别基于不同策略调整前序遍历顺序以达到后序遍历效果。

1077

被折叠的 条评论
为什么被折叠?



