94.144.145.二叉树的前中后序遍历

解法

  • 前序------根-左-右
  • 中序------左-根-右
  • 后序------左-右-根
    在这里插入图片描述
    递归法、迭代法、莫里斯法

解法1递归法

这是经典的方法,直截了当。我们可以定义一个辅助函数来实现递归。

  • 时间复杂度:O(n)O(n)。递归函数 T(n) = 2 \cdot T(n/2)+1T(n)=2⋅T(n/2)+1。
  • 空间复杂度:最坏情况下需要空间O(n)O(n),平均情况为O(\log n)O(logn)。
    牢记如下:
前序:
void fun(tree){
tree->val;
fun(tree->left);
fun(tree->right);
}
中序:
void fun(tree){
fun(tree->left);
tree->val;
fun(tree->right);
}
后序:
void fun(tree){
fun(tree->left);
fun(tree->right);
tree->val;
}

作者:183-3
链接:https://leetcode-cn.com/problems/binary-tree-inorder-traversal/solution/zhe-ti-ying-gai-shu-yu-di-gui-de-ji-chu-ti-ba-by-1/
1、前序遍历递归

前序遍历即访问顺序按照: root -> left -> rightroot−>left−>right的顺序,直至访问到空结点。按照这个思路很容易写出递归实现。代码如下:

作者:007havegone
链接:https://leetcode-cn.com/problems/binary-tree-preorder-traversal/solution/qian-xu-bian-li-by-007havegone/

/**
 * Definition for a binary tree node.
 * struct TreeNode {
 *     int val;
 *     TreeNode *left;
 *     TreeNode *right;
 *     TreeNode(int x) : val(x), left(NULL), right(NULL) {}
 * };
 */
class Solution {
public:
    vector<int> ret;
    vector<int> preorderTraversal(TreeNode* root) {
        pre_travel(root);
        return ret;
    }
    void pre_travel(TreeNode* root)
    {
        if(root)//当前结点非空
        {
            ret.push_back(root->val);//访问根节点
            pre_travel(root->left);//递归左子树
            pre_travel(root->right);//递归右子树
        }
    }
};
2、后序遍历递归

https://leetcode.com/problems/binary-tree-postorder-traversal/discuss/45550/C%2B%2B-Iterative-Recursive-and-Morris-Traversal

class Solution {
public:
    vector<int> postorderTraversal(TreeNode* root) {
        vector<int> nodes;
        postorder(root, nodes);
        return nodes;
    }
private:
    void postorder(TreeNode* root, vector<int>& nodes) {
        if (!root) {
            return;
        }
        postorder(root -> left, nodes);
        postorder(root -> right, nodes);
        nodes.push_back(root -> val);
    }
};
3、中序遍历递归
/**
 * Definition for a binary tree node.
 * struct TreeNode {
 *     int val;
 *     TreeNode *left;
 *     TreeNode *right;
 *     TreeNode(int x) : val(x), left(NULL), right(NULL) {}
 * };
 */
class Solution {
public:
    vector<int> inorderTraversal(TreeNode* root) {
        vector<int> res;
        helper(root,res);
        return res;
    }
    void helper(TreeNode* root,vector<int>& res){
        if(root==NULL) return;
        helper(root->left,res);
        res.emplace_back(root->val);
        helper(root->right,res);
    }
};

作者:24shi-01fen-_00_01
链接:https://leetcode-cn.com/problems/binary-tree-inorder-traversal/solution/die-dai-di-gui-by-24shi-01fen-_00_01-2/

解法2 迭代法

这里把前序、中序、后序的解法都列出来。内容来自如下链接:

https://leetcode-cn.com/problems/binary-tree-inorder-traversal/solution/die-dai-fa-by-jason-2/

  • 时间复杂度:O(n)O(n)。
  • 空间复杂度:O(n)O(n)。

解题思路

1、前序遍历迭代算法

当然还可以通过自己用栈来完成递归的功能。即我们访问根节点后,然后访问其左子树,当左子树遍历完成后,我们需要访问右子树,此时我们就需要拿到父节点的信息,通过父节点我们从而访问其右子树。这样整棵树完成遍历后,继续回退到上一层。直至当前子树访问完成,同时栈为空。

作者:007havegone
链接:https://leetcode-cn.com/problems/binary-tree-preorder-traversal/solution/qian-xu-bian-li-by-007havegone/

/**
 * Definition for a binary tree node.
 * struct TreeNode {
 *     int val;
 *     TreeNode *left;
 *     TreeNode *right;
 *     TreeNode(int x) : val(x), left(NULL), right(NULL) {}
 * };
 */
class Solution {
public:
    vector<int> preorderTraversal(TreeNode* root) {
        if(!root)return vector<int>();//空树,直接返回
        stack<TreeNode*> st;
        vector<int> ret;
        TreeNode* p=root;//p指向当前访问结点
        while(p||!st.empty())
        {
            while(p){//若当前结点非空
                ret.push_back(p->val);//访问该结点
                st.push(p);//记录该结点到栈,后面回退
                p=p->left;//进入左子树访问
            }
            // while条件的设置,保证下面st非空
            //若p非空,那么一定会压入新元素,此时st非空。若p为空,则st一定非空
            //按先序的,此时父节点已经访问,通过它拿到右孩子后就可以移除
            p=st.top();st.pop();
            p=p->right;//进入右子树访问
        }
        return ret;
    }
};
2、后序遍历迭代算法

我们可以用与前序遍历相似的方法完成后序遍历。
后序遍历与前序遍历相对称。
思路: 每到一个节点 A,就应该立即访问它。 然后将左子树压入栈,再次遍历右子树。
遍历完整棵树后,结果序列逆序即可。

作者:jason-2
链接:https://leetcode-cn.com/problems/binary-tree-inorder-traversal/solution/die-dai-fa-by-jason-2/

思路:

栈S;
p= root;
while(p || S不空){
    while(p){
        访问p节点;
        p的左子树入S;
        p = p的右子树;
    }
    p = S栈顶弹出;
}
结果序列逆序;
/**
 * Definition for a binary tree node.
 * struct TreeNode {
 *     int val;
 *     TreeNode *left;
 *     TreeNode *right;
 *     TreeNode(int x) : val(x), left(NULL), right(NULL) {}
 * };
 */
class Solution {
public:
    vector<int> postorderTraversal(TreeNode* root) {
        stack<TreeNode*> S;
        vector<int> v;
        TreeNode* rt = root;
        while(rt || S.size()){
            while(rt){
                S.push(rt->left);
                v.push_back(rt->val);
                rt=rt->right;
            }
            rt=S.top();S.pop();
        }
        reverse(v.begin(),v.end());
        return v;
    }
};
3、中序遍历迭代算法

思路:每到一个节点 A,因为根的访问在中间,将 A 入栈。然后遍历左子树,接着访问 A,最后遍历右子树。
在访问完 A 后,A 就可以出栈了。因为 A 和其左子树都已经访问完成。

作者:24shi-01fen-_00_01
链接:https://leetcode-cn.com/problems/binary-tree-inorder-traversal/solution/die-dai-di-gui-by-24shi-01fen-_00_01-2/

class Solution {
public:
    vector<int> inorderTraversal(TreeNode* root) {
        stack<TreeNode*> sk;
        vector<int> res;
        while(root || sk.size()){
            while(root){
                sk.push(root);
                root=root->left;
            }
            root=sk.top();sk.pop();
            res.emplace_back(root->val);
            root=root->right;
        }
        return res;      
    }
};

解法3 莫里斯法

C++ 二叉树Morris法前、中、后遍历全集,见如下链接:

https://leetcode-cn.com/problems/binary-tree-preorder-traversal/solution/c-er-cha-shu-morrisfa-qian-zhong-hou-bian-li-quan-/

Stkcd [股票代码] ShortName [股票简称] Accper [统计截止日期] Typrep [报表类型编码] Indcd [行业代码] Indnme [行业名称] Source [公告来源] F060101B [净利润现金净含量] F060101C [净利润现金净含量TTM] F060201B [营业收入现金含量] F060201C [营业收入现金含量TTM] F060301B [营业收入现金净含量] F060301C [营业收入现金净含量TTM] F060401B [营业利润现金净含量] F060401C [营业利润现金净含量TTM] F060901B [筹资活动债权人现金净流量] F060901C [筹资活动债权人现金净流量TTM] F061001B [筹资活动股东现金净流量] F061001C [筹资活动股东现金净流量TTM] F061201B [折旧摊销] F061201C [折旧摊销TTM] F061301B [公司现金流1] F061302B [公司现金流2] F061301C [公司现金流TTM1] F061302C [公司现金流TTM2] F061401B [股权现金流1] F061402B [股权现金流2] F061401C [股权现金流TTM1] F061402C [股权现金流TTM2] F061501B [公司自由现金流(原有)] F061601B [股权自由现金流(原有)] F061701B [全部现金回收率] F061801B [营运指数] F061901B [资本支出与折旧摊销比] F062001B [现金适合比率] F062101B [现金再投资比率] F062201B [现金满足投资比率] F062301B [股权自由现金流] F062401B [企业自由现金流] Indcd1 [行业代码1] Indnme1 [行业名称1] 季度数据,所有沪深北上市公司的 分别包含excel、dta数据文件格式及其说明,便于不同软件工具对数据的分析应用 数据来源:基于上市公司年报及公告数据整理,或相关证券交易所、各部委、省、市数据 数据范围:基于沪深北证上市公司 A股(主板、小企业板、创业板、科创板等)数据整理计算
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值