二叉树前序、中序、后序遍历递归与非递归版本、层序遍历

二叉树的层序遍历

思路:层序遍历采用队列即可。每次操作就是进行一层的遍历,将当前一层的值存进vector,并且如果当前节点的左右节点不为空,就丢进队列。

/**
 * 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<vector<int>> levelOrder(TreeNode* root) {
        vector<vector<int>> ans;
        queue<TreeNode*> que;
        if(root) que.push(root);
        while(!que.empty()){
            int siz=que.size();
            vector<int> a;
            while(siz--){
                TreeNode* now=que.front();
                que.pop();
                a.push_back(now->val);
                if(now->left) que.push(now->left);
                if(now->right) que.push(now->right);
            }
            ans.push_back(a);
        }
        return ans;
    }
};


二叉树的前序遍历

递归

思路:前序是中左右,所以先存根的值,然后dfs左右子树即可

/**
 * Definition for a binary tree node.
 * struct TreeNode {
 *     int val;
 *     TreeNode *left;
 *     TreeNode *right;
 *     TreeNode() : val(0), left(nullptr), right(nullptr) {}
 *     TreeNode(int x) : val(x), left(nullptr), right(nullptr) {}
 *     TreeNode(int x, TreeNode *left, TreeNode *right) : val(x), left(left), right(right) {}
 * };
 */
class Solution {
public:
    vector<int> ans;
    void dfs(TreeNode* root){
        if(!root) return ;
        ans.push_back(root->val);
        dfs(root->left);
        dfs(root->right);
    }
    vector<int> preorderTraversal(TreeNode* root) {
        dfs(root);
        return ans;
    }
};

非递归

思路:我们知道递归其实本质是栈,所以我们非递归的话,就用一个栈去模拟即可。
然后因为前序是中左右,而栈的栈顶是后加入的。
所以我们把左右结点丢入栈的时候,应该是先丢右节点,在丢左节点,这样子取出来的栈顶才是左节点。

/**
 * Definition for a binary tree node.
 * struct TreeNode {
 *     int val;
 *     TreeNode *left;
 *     TreeNode *right;
 *     TreeNode() : val(0), left(nullptr), right(nullptr) {}
 *     TreeNode(int x) : val(x), left(nullptr), right(nullptr) {}
 *     TreeNode(int x, TreeNode *left, TreeNode *right) : val(x), left(left), right(right) {}
 * };
 */
class Solution {
public:
    vector<int> ans;
    vector<int> preorderTraversal(TreeNode* root) {
        stack<TreeNode*> sta;
        if(root) sta.push(root);
        while(!sta.empty()){
            TreeNode* now=sta.top();
            sta.pop();
            ans.push_back(now->val);
            if(now->right) sta.push(now->right);
            if(now->left) sta.push(now->left);
        }
        return ans;
    }
};


二叉树的后序遍历

递归

思路:后序是左右中,所以先dfs左右子树,然后存根的值即可

/**
 * Definition for a binary tree node.
 * struct TreeNode {
 *     int val;
 *     TreeNode *left;
 *     TreeNode *right;
 *     TreeNode() : val(0), left(nullptr), right(nullptr) {}
 *     TreeNode(int x) : val(x), left(nullptr), right(nullptr) {}
 *     TreeNode(int x, TreeNode *left, TreeNode *right) : val(x), left(left), right(right) {}
 * };
 */
class Solution {
public:
    vector<int> ans;
    void dfs(TreeNode* root){
        if(!root) return ;
        dfs(root->left);
        dfs(root->right);
        ans.push_back(root->val);
    }
    vector<int> postorderTraversal(TreeNode* root) {
        dfs(root);
        return ans;
    }
};

非递归

思路:我们知道前序是中左右,后序是左右中,我们把前序的存的节点顺序反转一下那么reverse(前序)就是右左中,根据前面非递归版本的前序遍历,那么我们只要改变为先把左儿子进栈,再把右儿子进栈即可。这样出来就是中右左,整个vector反转一下就是左右中也就是后序了。

/**
 * Definition for a binary tree node.
 * struct TreeNode {
 *     int val;
 *     TreeNode *left;
 *     TreeNode *right;
 *     TreeNode() : val(0), left(nullptr), right(nullptr) {}
 *     TreeNode(int x) : val(x), left(nullptr), right(nullptr) {}
 *     TreeNode(int x, TreeNode *left, TreeNode *right) : val(x), left(left), right(right) {}
 * };
 */
class Solution {
public:
    vector<int> ans;
    vector<int> postorderTraversal(TreeNode* root) {
        stack<TreeNode*> sta;
        if(root) sta.push(root);
        while(!sta.empty()){
            TreeNode* now=sta.top();
            sta.pop();
            ans.push_back(now->val);
            //与前序非递归相比,这两行顺序换了换而已
            if(now->left) sta.push(now->left);
            if(now->right) sta.push(now->right);
        }
        reverse(ans.begin(),ans.end());//中右左 反转  左右中
        return ans;
    }
};


二叉树的中序遍历

递归

思路:中序是左中右,所以先dfs左子树,然后存根的值,最后dfs右子树

/**
/**
 * Definition for a binary tree node.
 * struct TreeNode {
 *     int val;
 *     TreeNode *left;
 *     TreeNode *right;
 *     TreeNode() : val(0), left(nullptr), right(nullptr) {}
 *     TreeNode(int x) : val(x), left(nullptr), right(nullptr) {}
 *     TreeNode(int x, TreeNode *left, TreeNode *right) : val(x), left(left), right(right) {}
 * };
 */
class Solution {
public:
    vector<int> ans;
    void dfs(TreeNode* root){
        if(!root) return ;
        dfs(root->left);
        ans.push_back(root->val);
        dfs(root->right);
    }
    vector<int> inorderTraversal(TreeNode* root) {
        dfs(root);
        return ans;
    }
};

非递归

思路:前面的非递归版本,我们其实一定会先存根结点的值,所以很遗憾,这里不能和前面非递归做法高度一致。那么我们知道中序是左中右,其实就是一直左子树递归。
所以本质思想就是不撞南墙不回头,也就是如果左子树不空,那么一直递归下去。
空了呢?我们取上一个结点,这个结点已经遍历过左子树了,所以开始遍历它的右子树。而因为是左中右,所以继续遍历右子树的左子树。

/**
 * Definition for a binary tree node.
 * struct TreeNode {
 *     int val;
 *     TreeNode *left;
 *     TreeNode *right;
 *     TreeNode() : val(0), left(nullptr), right(nullptr) {}
 *     TreeNode(int x) : val(x), left(nullptr), right(nullptr) {}
 *     TreeNode(int x, TreeNode *left, TreeNode *right) : val(x), left(left), right(right) {}
 * };
 */
class Solution {
public:
    vector<int> ans;
    vector<int> inorderTraversal(TreeNode* root) {
        stack<TreeNode*> sta;
        while(root || !sta.empty()){
            if(root){		//没撞南墙 一直遍历左子树
                sta.push(root);		//保存过来的结点
                root=root->left;
            }
            else{			//撞墙了
                root=sta.top();//取出上一个遍历的点
                sta.pop();
                ans.push_back(root->val);//
                root=root->right;//开始跑右子树
            }
        }
        return ans;
    }
};
  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 2
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

我不会c语言

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值