【递归】二叉树遍历(中序、前序、后序、层次)

本文介绍了二叉树的四种遍历方式:中序、前序、后序以及层次遍历。通过递归和非递归方法展示了它们的实现,并提供了对应的LeetCode题目。中序遍历采用左根右的顺序,前序遍历为根左右,后序遍历为左右根。层次遍历则按层输出节点。对于非递归中序遍历,利用了栈来辅助完成。
摘要由CSDN通过智能技术生成

二叉树是一种重要的必须要掌握的数据结构,也是面试官经常问到的。本篇整理一下二叉树的基本操作:遍历

二叉树的遍历有4种:中序、前序(也叫先序)、后序、层次,前3种属于深度优先搜索(动画演示),后1种属于广度优先搜索(动画演示)。

中序、前序、后序:

中序、前序、后序是根据访问根节点的顺序决定的,先访问根节点叫前序,后访问根节点叫后序,中间访问根节点叫中序,所以他们的访问顺序如下:

中序:左子树 -> 根节点 -> 右子树(动画演示

前序:根节点 -> 左子树 -> 右子树(动画演示

后序:左子树 -> 右子树 -> 根节点(动画演示

递归:

二叉树中常用递归,书写简洁,后面代码多以递归为主。

中序代码:

class Solution {
public:
    vector<int> inorderTraversal(TreeNode* root) {
        vector<int> ret;
        visit(root, &ret);
        return ret;
    }
    void visit(TreeNode* root, vector<int> *ret) {
        // 左 中 右
        if (root == NULL) return;
        visit(root->left, ret);
        ret->push_back(root->val);
        visit(root->right, ret);
    }
};

对应leetcode:94. 二叉树的中序遍历

前序代码:

class Solution {
public:
    vector<int> preorderTraversal(TreeNode* root) {
        vector<int> ret;
        visit(root, &ret);
        return ret;
    }
    void visit(TreeNode* root, vector<int> *ret) {
        // 中 左 右
        if (root == NULL) return;
        ret->push_back(root->val);
        visit(root->left, ret);
        visit(root->right, ret);
    }
};

对应leetcode:144. 二叉树的前序遍历

后序代码:

class Solution {
public:
    vector<int> postorderTraversal(TreeNode* root) {
        vector<int> ret;
        visit(root, &ret);
        return ret;
    }
    void visit(TreeNode* root, vector<int> *ret) {
        // 左 右 中
        if (root == NULL) return;
        visit(root->left, ret);
        visit(root->right, ret);
        ret->push_back(root->val);
    }
};

对应leetcode:145. 二叉树的后序遍历

中序非递归实现:

深度优先搜索非递归实现需要借助,中序遍历代码如下,代码比递归实现复杂且难懂。

class Solution {
public:
    vector<int> inorderTraversal(TreeNode* root) {
        vector<int> ret;
        stack<TreeNode*> st;
        // 一直压左子树入栈
        TreeNode *p = root;
        while (p) {
            st.push(p);
            p = p->left;
        }
        while (!st.empty()) {
            p = st.top(); st.pop();
            ret.push_back(p->val);
            p = p->right;
            while (p) { // 继续左子树入栈
                st.push(p);
                p = p->left;
            }
        }
        return ret;
    }
};

层次遍历:

按层依次输出,例如下图4,5和7在同一层,层次遍历依次输出:1,2,3,4,5,7,8。(动画演示

层次遍历需要借助队列实现,将每一层的节点入队列,遍历队列的同时生成下一层的节点队列,代码如下(代码中2层的节点队列使用了同一个变量q存储,通过size来划分):

class Solution {
public:
    vector<vector<int>> levelOrder(TreeNode* root) {
        vector<vector<int>> result;
        // 层次遍历
        queue<TreeNode*> q;
        if (root) q.push(root);
        while (!q.empty()) {
            vector<int> level;
            int size = q.size();
            for (int i = 0; i < size; i++) {
                 TreeNode* t = q.front(); q.pop();
                 level.push_back(t->val);
                 if (t->left) q.push(t->left);
                 if (t->right) q.push(t->right);
            }
            result.push_back(level);
        }
        return result;
    }
};

对应leetcode:剑指 Offer 32 - II. 从上到下打印二叉树 II

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值