LeetCode 94.144.145. 使用递归和非递归方式解决二叉树的三种遍历问题

二叉树的遍历问题可以说是基础内容,而且必须要掌握的,下面我将使用递归和辅助栈的方式来实现二叉树的前、中、后序遍历!具体的理论和实现思路,可以看一下左神的算法面试课程中的二叉树(1),再进行编码和实践,有啥疑惑可以评论区留言哈!

1 使用递归方式实现三种遍历方式

1.1 前序遍历

遍历方式: 根 -> 左 -> 右

class Solution {
public:
	vector<int> res;
    void dfs(TreeNode* node) {
        if(node == nullptr) return ;
        res.push_back(node->val);
        dfs(node->left);
        dfs(node->right);
    }
    vector<int> preorderTraversal(TreeNode* root) {
        if(root == NULL) return res;
        dfs(root);
        return res;
    }
};

时间复杂度:O(N) ,访问每个节点恰好一次
空间复杂度:O(N),取决于树的结构,最坏情况存储整棵树,因此空间复杂度是 O(N)
ps:本文章中的时间、空间复杂度都是O(N),为了文章的简洁性,下面将不再阐述

1.2 中序遍历

遍历方式: 左 -> 根 -> 右

class Solution {
public:
	vector<int> res;
    void dfs(TreeNode* node) {
        if(node == nullptr) return ;
        dfs(node->left);
        res.push_back(node->val);
        dfs(node->right);
    }
    vector<int> inorderTraversal(TreeNode* root) {
        if(root == NULL) return res;
        dfs(root);
        return res;
    }
};

1.3 后序遍历

遍历方式: 左 -> 右 -> 根

class Solution {
public:
	vector<int> res;
    void dfs(TreeNode* node) {
        if(node == nullptr) return ;
        dfs(node->left);
        dfs(node->right);
        res.push_back(node->val);
    }
    vector<int> postorderTraversal(TreeNode* root) {
        if(root == NULL) return res;
        dfs(root);
        return res;
    }
};

2 使用非递归方式实现三种遍历方式

2.1 前序遍历

遍历方式: 根 -> 左 -> 右

class Solution {
public:
    vector<int> preorderTraversal(TreeNode* root) {
        vector<int> res;
        if(root == NULL) return res;
        stack<TreeNode*> s;
        s.push(root);
        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;
    }
};

2.2 后序遍历(注意这里是后序遍历emmm)

遍历方式: 左 -> 右 -> 根

方法一:前序遍历的顺序为 根->左->右,与后序遍历的逆序(根->右->左)有些相似,因此可以使用前序遍历的思想,最后再倒置向量即可。

class Solution {
public:
    vector<int> postorderTraversal(TreeNode* root) {
        vector<int> res;
        if(root == NULL) return res;
        stack<TreeNode*> s;
        s.push(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;
        if(root == NULL) return res;
        stack<TreeNode*> s1, s2;
        s1.push(root);
        while(!s1.empty()) {
            TreeNode* cur = s1.top();
            s1.pop();
            s2.push(cur);
            if(cur->left) s1.push(cur->left);
            if(cur->right) s1.push(cur->right);
        }
        while(!s2.empty()) res.push_back(s2.top()->val), s2.pop();
        return res;
    }
};

方法三:使用一个栈实现

class Solution {
public:
    vector<int> postorderTraversal(TreeNode* root) {
        vector<int> res;
        if(root == NULL) return res;
        stack<TreeNode*> s;
        s.push(root);
        TreeNode* h;               //最近一次弹出的结点
        TreeNode* cur;
        h = root, cur = NULL;
        while(!s.empty()) {
            cur = s.top();
            if(cur->left && h != cur->left && h != cur->right) {
                s.push(cur->left);
            } else if(cur->right && h != cur->right) {
                s.push(cur->right);
            } else {
                res.push_back(cur->val);
                s.pop();
                h = cur;
            }
        }
        return res;
    }
};

2.3 中序遍历

遍历方式: 左 -> 根 -> 右

class Solution {
public:
    vector<int> inorderTraversal(TreeNode* root) {
        vector<int> res;
        if(root == NULL) return res;
        stack<TreeNode*> s;
        TreeNode* cur = root;
        while(cur != NULL || !s.empty()) {
            while(cur != NULL) {
                s.push(cur);
                cur = cur->left;
            }
            cur = s.top(), s.pop();
            res.push_back(cur->val);
            cur = cur->right;
        }
        return res;
    }
};

结语:①如果你是小白,之前没有接触过二叉树相关问题的话,代码可能会有点难理解。可以跟着文章开头的视频链接,跟着思路,并食用代码实现,反复练习效果更佳!(可以先记住一个简单常用的套路解决问题)
②如果你是个大佬,对上述代码有什么改进或优化的地方,欢迎指出!

  • 1
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值