栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > C/C++/C#

算法学习 - 二叉树遍历

C/C++/C# 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

算法学习 - 二叉树遍历

  • 参考:《labuladong的算法小抄》
  • 参考: 二叉树的三种遍历递归与迭代写法

文章目录
  • 深度优先遍历
    • 递归
    • 迭代
      • 前序遍历
      • 中序遍历
      • 后序遍历
  • 广度优先遍历
  • 节点定义

深度优先遍历

二叉树遍历的深度优先遍历可以通过递归和迭代来实现.

递归

递归方法遍历二叉树比较简单, 只要注意处理数据的代码的位置即可.

void traverse(TreeNode* root)
{
    if(root == nullptr) return;
    // 前序遍历代码
    traverse(root->left);
    // 中序遍历代码
    traverse(root->right);
    // 后序遍历代码
}
迭代

二叉树遍历的迭代解法使用栈数据结构来模拟递归调用.

前序遍历
void preorderTraverse(TreeNode* root)
{
    stack st;
    st.push(root);
    while(!st.empty())
    {
        int sz = st.size();
        for(int i = 0; i
            TreeNode *cur = st.top();
            st.pop();
            if(cur != nullptr)
            {
                //对cur指向的节点的数据进行处理
                //...
                //注意先右后左!!
                if(cur->right != nullptr) st.push(cur->right);
                if(cur->left != nullptr) st.push(cur->left);
            }
        }
    }
}
中序遍历
void inorderTraverse(TreeNode* root)
{
    stack st;
    TreeNode* cur = root;
    while(cur || !st.empty())
    {
        while(cur)
        {
            st.push(cur);
            cur = cur->left;
        }
        cur = st.top();
        st.pop();
        //处理当前节点数据
        //...
        cur = cur->right;
    }
}
后序遍历
void postorderTraverse(TreeNode* root)
{
    stack st;
    TreeNode* cur = root;
    TreeNode* prev = nullptr;	//需要记录前置的访问节点
    while(cur || !st.empty())
    {
        //将当前节点和所有的左子树节点压入栈中
        while(cur)
        {
            st.push(cur);
            cur = cur->left;
        }
        //此时cur为null, 弹出栈顶元素
        cur = st.top();
        st.pop();
        //如果当前节点的右子树为空 或 之前访问的节点是自己的右子树 
        if(cur->right == nullptr || prev == cur->right)
        {
            //对数据节点处理
            //...
            prev = cur;
            cur = nullptr;	//注意将当前节点置为空, 否则下轮循环将访问节点的左子树
        }
        else 
        {
            st.push(cur);
            cur = cur->right;
        }
    }
}

另一种解法:
结点访问的顺序:

  • 前序遍历: root->left->right
  • 后序遍历: left->right->root

因此使用前序遍历的代码, 我们可以先将左子树入栈, 再将有子树入栈, 这样得到的遍历顺序是: root->right->left, 最后将所得的结果反向即可

vector postorderTraverse_2(TreeNode* root)
{
    vector ret;
    stack st;
    st.push(root);
    while(!st.empty())
    {
        int sz = st.size();
        for(int i = 0; i
            TreeNode* cur = st.top();
            st.pop();
            if(cur) ret.emplace_back(cur->val);
            if(cur->left) st.emplace(cur->left);
            if(cur->right) st.emplace(cur->right);
        }
    }
    reverse(ret.begin(), ret.end());
    return ret;
}
广度优先遍历
void BFS(TreeNode *root)
{
    queue q;
    q.push(root);
    while(!q.empty())
    {
        int sz = q.size();
        for(int i = 0; i
            TreeNode* cur = q.front();
            q.pop();
            if(cur)
            {
                //对节点数据的操作
                //...
                if(cur->left) q.push(cur->left);
                if(cur->right) q.push(cur->right);
            }
        }
    }
}
节点定义
class TreeNode
{
public:
    TreeNode(){}
    TreeNode(int _val):val(_val){}
    ~TreeNode(){}

    int val;
    TreeNode *left;
    TreeNode *right;
};
转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/928620.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号