【LeetCode】day13:144 94 145 - 二叉树的前、中、后序遍历, 102 - 二叉树的层序遍历

144 94 145.二叉树的前、中、后序遍历

题目描述:

给定一个二叉树的根节点root,返回它的前序、中序、后序遍历

递归方式

对二叉树按递归方式进行遍历,可以从整体把状态分为处理当前节点、处理左节点和处理右节点,左节点和右节点可能为子树需通过递归处理但在考虑时是作为整体的。而对于当前节点的处理所在位置,决定了当前遍历是前序、中序还是后序,框架如下:

class Solution {
private:
    void traverse(TreeNode* root, vector<int>& res) {
        if (root == nullptr) return;
        /*
		 * 此处在最前处理当前节点,为前序遍历
		 */
        traverse(root->left, res); // 此处处理当前节点的左节点
        /*
		 * 此处左节点和右节点之间处理当前节点,为中序遍历
		 */
        traverse(root->right, res); // 此处处理当前节点的右节点
        /*
		 * 此处在处理完左右节点的末尾处理当前节点,为后序遍历
		 */
    } 

public:
    vector<int> XXXTraversal(TreeNode* root) {
        vector<int> res;
        traverse(root, res);
        return res;
    }
};

迭代方式

对二叉树按迭代方式遍历,原理相同都是根据处理当前节点相对于处理左右节点的位置来区分前、中、后序,但不如递归方式直观。而且由于是通过迭代使用栈模拟递归的过程,对于前中后序的代码也不如真正的递归整齐(统一的递归方式需压入空指针不够美观不好理解所以不考虑),建议作为练习之用。
对于前序遍历,顺序是当前节点->左子树->右子树,按照栈先入后出的特性在处理完当前节点后先压入right后压入left,代码如下:

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

对于中序遍历,顺序是左子树->当前节点->右子树,所以不能向前序一样从栈中获取当前节点。而是相当于首先一路向左(cur = cur->left)前进到最左叶子节点,并将沿途遇到的所有节点(当前节点)入栈。直到走到尽头(cur == nullptr),获取栈顶元素作为结果,并将当前节点指向当前节点的右节点。
在这里插入图片描述
如上图,始终按照左->中->右的顺序前进,代码如下:

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

对于后序遍历,直接按后序的顺序实现会比较麻烦,因为是左->右->中的顺序,不仅需要判断左右是否为空,还需要判断当前节点在树中的位置比如是否有子树并分别处理。但是观察到后序的逆序是中->右->左,相当于先右子树后左子树的前序遍历。所以按照与前序相同的方法,只是入栈时按照相反的顺序先左后右,并在遍历之后逆序即可,代码如下:

class Solution {
public:
    vector<int> postorderTraversal(TreeNode* root) {
        if (root == nullptr) return {};
        vector<int> res;
        stack<TreeNode*> stk;
        stk.push(root);
        while (!stk.empty()) {
            TreeNode* cur = stk.top();
            stk.pop();
            res.push_back(cur->val);
            if (cur->left) stk.push(cur->left);
            if (cur->right) stk.push(cur->right);
        }
        reverse(res.begin(), res.end());
        return res;
    }
};

102.二叉树的层序遍历

题目描述:

给定二叉树的根节点root,返回其节点值的层序遍历。(即逐层地,从左到右访问所有节点)。

二叉树的层序遍历相当于从最顶层开始,逐层向下遍历。思路为按层处理节点,使用队列进行记录,如下图所示
在这里插入图片描述
每次循环都代表处理一层,循环开始时获取队列的size表示当前层所包含的节点数量,依次出队处理:获取当前节点并将其左右节点(若不为空)压入队列,最后将当前层的所有节点值记录压入res,持续循环直到队列为空表示当前层无节点。代码如下:

class Solution {
public:
    vector<vector<int>> levelOrder(TreeNode* root) {
        vector<vector<int>> res;
        if (root == nullptr) return res;
        queue<TreeNode*> q;
        q.push(root);
        while (!q.empty()) {
            int size = q.size();
            vector<int> curLevel;
            while (size-- > 0) {
                TreeNode* cur = q.front();
                q.pop();
                curLevel.push_back(cur->val);
                if (cur->left) q.push(cur->left);
                if (cur->right) q.push(cur->right);
            }
            res.push_back(curLevel);
        }
        return res;
    }
};
  • 16
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值