遍历二叉树的三种方法的六种实现

遍历二叉树的三种方法的六种实现

有详细(相对)的注释

(1)先序

力扣144.二叉树的前序遍历
https://leetcode-cn.com/problems/binary-tree-preorder-traversal/

递归:

class Solution
{
public:
    void dfs(TreeNode *root, vector<int> &vec)
    {
        if (root != nullptr)
        {
            vec.push_back(root->val);
            dfs(root->left, vec);
            dfs(root->right, vec);
            return;
        }
        else
            return;
    }
    vector<int> preorderTraversal(TreeNode *root)
    {
        vector<int> re;
        dfs(root, re);
        return re;
    }
};

栈:
怎么用栈实现呢。
先序遍历的过程是,访问中间的节点,再访问他的左子树和右子树。左子树也是先根节点,再左左子树。
所以,先访问根节点,然后访问左子树,根节点进栈,出栈的时候取出他的右子树这样?
比如根节点出栈,就访问右节点(右子树的根节点),它进栈,访问左子树


class Solution {
public:

    vector<int> preorderTraversal(TreeNode *root) {
        stack<TreeNode *> stk;
        vector<int> re;
        TreeNode *now = nullptr;
        if (root != nullptr) {
            re.push_back(root->val);
            stk.push(root);
            now = root->left;
        }

        while (!stk.empty()) {
            if (now != nullptr) {
                re.push_back(now->val);
                stk.push(now);
                now = now->left;
            } else {
                //now是空指针,上一个出栈,访问右
                TreeNode *middle = stk.top(); //就是他左节点是空的
                stk.pop();

                TreeNode *right_node = middle->right;
                if (right_node != nullptr) {
                    re.push_back(right_node->val);
                    stk.push(right_node);
                    //现在 right_node是这颗右子树的middle
                    now = right_node->left;
                } else continue;  //右节点也是空的
            }
        }
        return re;
    }
};

(2)中序

递归:

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

循环:
就是把所有左节点都进栈。直到空指针就访问上一个左节点。

    vector<int> inorderTraversal(TreeNode* root) {
        vector<int> re;
        stack<TreeNode*>stk;
        auto now = root;
        while(stk.empty()==0 || now!= nullptr){
            if(now!= nullptr){  //这里可以用一个while遍历入栈左边一条链
                stk.push(now);
                now = now->left;
            } else {
                re.push_back(stk.top()->val);
                now = stk.top()->right;
                stk.pop();
            }
        }
        return re;
    }

(3)后序

递归:懒得写了
循环:遇到的问题是,出栈中间节点的时候,不知道右边有没有遍历过。【利用pre记录上一个访问过的结点 左节点】

class Solution {
public:
    vector<int> postorderTraversal(TreeNode* root) {
        vector<int>re;
        stack<TreeNode*>stk;
        auto now = root;
        TreeNode* pre = nullptr;
        while(!stk.empty() || now!= nullptr ){
            while(now!= nullptr){
                stk.push(now);
                now = now->left;
            }
            auto middle = stk.top();
            stk.pop();
            if(middle->right== nullptr||pre==middle->right){
                re.push_back(middle->val);
                pre = middle;

            }else{
                now = middle->right;
                stk.push(middle);  //这里没想到
            }
        }
        return re;
   }
};

(4)一种不同的迭代 层次遍历

之前都是用的栈,这种用队列。

class Solution {
public:
    vector<vector<int>> levelOrder(TreeNode* root) {
        queue<TreeNode*>nodes;
        vector <vector<int>>re;
        if(!root) return re;
        nodes.push(root);
        while( !nodes.empty()){
            auto size = nodes.size();
            vector<int> line;
            for(int i =1; i<=size; i++){  //这里没想到
                auto now = nodes.front(); nodes.pop();
                line.push_back(now->val);
                if(now->left) nodes.push(now->left);
                if(now->right) nodes.push(now->right);
            }            
            re.push_back(line);
        }
        return re;
    }
};
//ret.push_back(vector <int> ());
// ret.back().push_back(node->val);

学到一个C++vector这样插入一行的办法

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值