144. 二叉树的前序遍历
94. 二叉树的中序遍历
145. 二叉树的后序遍历
//递归
//确定递归参数和返回值 确定递归出口 确定单层逻辑
void dfs(TreeNode* root, vector<int>&result){
if(!root) return;
result.push_back(root->val); // 放在这是前序遍历
dfs(root->left, result);
//result.push_back(root->val); // 放在这是中序遍历
dfs(root->right, result);
//result.push_back(root->val); // 放在这是后序遍历
}
使用栈模拟递归过程
//整体流程
stack<TreeNode*>s;
vector<int>reslut;
while(root||!s.empty()){
if(root不为空){
左子节点入栈
}else{
拿出栈顶元素
判断栈顶元素是否出栈
当前节点指向栈顶元素的右子节点
}
}
前序和中序遍历都是一次入栈,区别就是访问的时刻,
前序在入栈访问,中序在出栈时访问
//非递归
class Solution {
public:
vector<int> preorderTraversal(TreeNode* root) {
stack<TreeNode*>s;
vector<int>reslut;
while(root||!s.empty()){
if(root){
s.push(root);
reslut.push_back(root->val);//前序遍历访问
root = root->left;
}else{
TreeNode *node = s.top();
// reslut.push_back(node->val); //中序遍历访问
s.pop();
root = node->right;
}
}
return reslut;
}
};
后序遍历的访问要求在右子节点访问之后,那么要不要进行出栈就要看以下两个条件
- 它的右子节点为空 该节点出栈
- 上一次出栈的是它的右子节点,该节点出栈,
class Solution {
public:
vector<int> postorderTraversal(TreeNode* root) {
vector<int>result;
stack<TreeNode*>s;
TreeNode * pre = nullptr; // 记录上一个出栈的节点
while(root || !s.empty()){
if(root){
s.push(root);
root = root->left;
}else{
TreeNode *node = s.top();
if(!node->right || node->right == pre){//右节点为空或者上一次出栈的是自己的右节点
result.push_back(node->val);
s.pop();
pre = node;
root = nullptr; // 因为出栈,下一个节点还是要从栈里弹出进行判断,所以这里要重新设置以下root
}else{
root =node->right; //不符合出栈要求那么就将其右节点压栈
}
}
}
return result;
}
};