二叉树遍历引出递归树算法框架

详细描述了递归
什么是前中后序遍历
在这里插入图片描述

[前序]对于当前节点,先输出该节点,然后输出他的左孩子,最后输出他的右孩子。以上图为例,递归的过程如下:
(1):输出 1,接着左孩子;
(2):输出 2,接着左孩子;
(3):输出 4,左孩子为空,再接着右孩子;
(4):输出 6,左孩子为空,再接着右孩子;
(5):输出 7,左右孩子都为空,此时 2 的左子树全部输出,2 的右子树为空,此时 1 的左子树全部输出,接着 1 的右子树;
(6):输出 3,接着左孩子;
(7):输出 5,左右孩子为空,此时 3 的左子树全部输出,3 的右子树为空,至此 1 的右子树全部输出,结束。
[中序]对于当前结点,先输出它的左孩子,然后输出该结点,最后输出它的右孩子。以上图为例:
(1):1-->2-->4,4 的左孩子为空,输出 4,接着右孩子;
(2):6 的左孩子为空,输出 6,接着右孩子;
(3):7 的左孩子为空,输出 7,右孩子也为空,此时 2 的左子树全部输出,输出 2,2 的右孩子为空,此时 1 的左子树全部输出,输出 1,接着 1 的右孩子;
(4):3-->5,5 左孩子为空,输出 5,右孩子也为空,此时 3 的左子树全部输出,而 3 的右孩子为空,至此 1 的右子树全部输出,结束。
[后序]对于当前结点,先输出它的左孩子,然后输出它的右孩子,最后输出该结点。依旧以上图为例:
(1):1->2->4->6->7,7 无左孩子,也无右孩子,输出 7,此时 6 无左孩子,而 6 的右子树也全部输出,输出 6,此时 4 无左子树,而 4 的右子树全部输出,输出 4,此时 2 的左子树全部输出,且 2 无右子树,输出 2,此时 1 的左子树全部输出,接着转向右子树;
(2):3->5,5 无左孩子,也无右孩子,输出 5,此时 3 的左子树全部输出,且 3 无右孩子,输出 3,此时 1 的右子树全部输出,输出 1,结束。

自顶向下

递归有点像stack,先进后出

“自顶向下” 意味着在每个递归层级,我们将首先访问节点来计算一些值,并在递归调用函数时将这些值传递到子节点。 所以 “自顶向下” 的解决方案可以被认为是一种前序遍历。 具体来说,递归函数 top_down(root, params) 的原理是这样的:

1. return specific value for null node
2. update the answer if needed                      // anwer <-- params
3. left_ans = top_down(root.left, left_params)      // left_params <-- root.val, params
4. right_ans = top_down(root.right, right_params)   // right_params <-- root.val, params
5. return the answer if needed                      // answer <-- left_ans, right_ans

前序遍历

class Solution {
public:
    void pre_travel(TreeNode* root,vector<int>& res)
    {
        if(root)
        {
            res.push_back(root->val);
            pre_travel(root->left,res);
            pre_travel(root->right,res);
        }
    }
    vector<int> preorderTraversal(TreeNode* root) {
        vector<int> res;
        pre_travel(root,res);
        return res;


    }

};

自底向上

“自底向上” 是另一种递归方法。 在每个递归层次上,我们首先对所有子节点递归地调用函数,然后根据返回值和根节点本身的值得到答案。 这个过程可以看作是后序遍历的一种。 通常, “自底向上” 的递归函数 bottom_up(root) 为如下所示:

1. return specific value for null node
2. left_ans = bottom_up(root.left)          // call function recursively for left child
3. right_ans = bottom_up(root.right)        // call function recursively for right child
4. return answers                           // answer <-- left_ans, right_ans, root.val

后序遍历

class Solution {
public:
    vector<int> postorderTraversal(TreeNode* root) {
        vector<int> res;
        hid_travel(root,res);
        return res;
    }
    void hid_travel(TreeNode* root,vector<int>& res)
    {
        if(root)
        {
            hid_travel(root->left,res);
            hid_travel(root->right,res);
            res.push_back(root->val);
        }
    }
};

在这里插入图片描述

中序遍历

class Solution {
public:
    vector<int> inorderTraversal(TreeNode* root) {
        vector<int> res;
        med_travel(root,res);
        return res;
    }
    void med_travel(TreeNode* root,vector<int>& res)
    {
        if(root)
        {
            med_travel(root->left,res);
            res.push_back(root->val);
            med_travel(root->right,res);
        }
    }
};

到了最后,其实每一个子节点就是子问题,递归的解决其实就是子问题的遍历,只是方式有前中后几种以及优化剪枝

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值