【C++】非递归实现二叉树的前中后序遍历

简介: 【C++】非递归实现二叉树的前中后序遍历

👉二叉树的前序遍历👈


前序遍历的顺序是根、左子树、右子树。那么首先访问的一定是左路节点,再来访问左路节点的右子树。而访问左路节点的右子树又可以看成一个子问题,那么就能像递归访问整棵树了。


思路:

想定义一个栈st、一个vector v和一个TreeNode* cur,cur初始化为root。

当cur不为空或者st不为空时,while继续。while循环里做一下操作:左路节点入栈的同时尾插到v中,那么左路节点就访问完了。然后取出栈顶节点top,将cur置为top->right,这样就可以转化成子问题去访问左路节点的右子树了。

cur不为空表示要访问一棵树,st不为空表示还有左路节点的右子树没有访问。两个同时为空时,while循环结束,得到正确的前序遍历。

注:一个节点出栈意味着这个节点及其左子树已经访问完了,还剩右子树没有访问。


8448a4c704784db0a9ba8a932d3af556.png

class Solution 
{
public:
    vector<int> preorderTraversal(TreeNode* root) 
    {
        stack<TreeNode*> st;
        vector<int> v;
        TreeNode* cur = root;
        // cur 不为空表示要访问一棵树
        // st 不为空表示还有右子树没有访问
        while(cur || !st.empty())
        {
            // 开始访问整棵树
            // 1.访问左路节点
            while(cur)
            {
                v.push_back(cur->val);
                st.push(cur);
                cur = cur->left;
            }
            // 转化成子问题:访问左路节点的右子树
            TreeNode* top = st.top();
            st.pop();
            cur = top->right;   // 子问题访问右子树
        }
        return v;
    }
};


f8f3cb8fef7846fe99cefc2a56eec70d.png


👉二叉树的中序遍历👈


中序遍历的顺序是左子树、根、右子树。首先,和中序遍历一样的是左路节点入栈,入栈的同时不能访问该节点,即不能将节点的值尾插到vector中。当左路节点出栈时,表示当前节点的左子树已经访问完了,开始访问当前节点及其右子树。


class Solution 
{
public:
    vector<int> inorderTraversal(TreeNode* root) 
    {
        stack<TreeNode*> st;
        vector<int> v;
        TreeNode* cur = root;
        while(cur || !st.empty())
        {
            // 1.左路节点入栈
            while(cur)
            {
                st.push(cur);
                cur = cur->left;
            }
            // 2.当左路节点出栈时,表示左子树已经访问过了,应该
            // 访问这个节点和它的右子树
            TreeNode* top = st.top();
            st.pop();
            v.push_back(top->val);  // 访问这个节点
            cur = top->right;   // 转化成子问题访问右子树
        }
        return v;
    }
};

b6207e09aa4b420e9678182573f604d3.png


👉二叉树的后序遍历👈


后序遍历的顺序是左子树、右子树、根,需要将左子树和右子树访问完了,才能访问根。如果栈顶节点为空或者栈顶节点的右子树已经访问过了,就可以访问栈顶节点了。为了知道是否已经访问过栈顶节点的右子树,我们可以通过prev来记录上一次访问的节点。当prev等于top->right时,表示栈顶节点的右子树已经访问过了,可以弹出栈顶节点并访问它。


4849d797230e42df9909c7cd33f69ffe.png

class Solution 
{
public:
    vector<int> postorderTraversal(TreeNode* root) 
    {
        vector<int> v;
        stack<TreeNode*> st;
        TreeNode* cur = root;
        TreeNode* prev = nullptr;
        while(cur || !st.empty())
        {
            // 左路节点入栈
            while(cur)
            {
                st.push(cur);
                cur = cur->left;
            }
            TreeNode* top = st.top();   // 取栈顶节点但不pop
            // 栈顶节点右子树为空或者上一次访问的节点是top右子树的根,说明右子树已经访问过了
            // 可以访问栈顶节点,否则转换成子问题访问top的右子树
            if(top->right == nullptr || top->right == prev)
            {
                st.pop();
                v.push_back(top->val);
                prev = top;
                cur = nullptr;  // cur为空表示弹出的栈顶节点没有右子树或者右子树已经访问过了
            }
            else
                cur = top->right;
        }
        return v;
    }
};


a5bac6be2fb447c0b2c38ff018de6c73.png


👉总结👈


本篇的非递归实现二叉树的前中后序遍历都差不多是一个思路,左路节点先入栈。最大的区别就是栈顶节点的访问时机不同。那么以上就是本篇博客的全部内容了,如果大家觉得有收获的话,可以点个三连支持一下!谢谢大家!💖💝❣️










相关文章
|
2月前
|
Java C++
【C++数据结构——树】二叉树的基本运算(头歌实践教学平台习题)【合集】
本关任务:编写一个程序实现二叉树的基本运算。​ 相关知识 创建二叉树 销毁二叉树 查找结点 求二叉树的高度 输出二叉树 //二叉树节点结构体定义 structTreeNode{ intval; TreeNode*left; TreeNode*right; TreeNode(intx):val(x),left(NULL),right(NULL){} }; 创建二叉树 //创建二叉树函数(简单示例,手动构建) TreeNode*create
61 12
|
2月前
|
C++
【C++数据结构——树】二叉树的性质(头歌实践教学平台习题)【合集】
本文档介绍了如何根据二叉树的括号表示串创建二叉树,并计算其结点个数、叶子结点个数、某结点的层次和二叉树的宽度。主要内容包括: 1. **定义二叉树节点结构体**:定义了包含节点值、左子节点指针和右子节点指针的结构体。 2. **实现构建二叉树的函数**:通过解析括号表示串,递归地构建二叉树的各个节点及其子树。 3. **使用示例**:展示了如何调用 `buildTree` 函数构建二叉树并进行简单验证。 4. **计算二叉树属性**: - 计算二叉树节点个数。 - 计算二叉树叶子节点个数。 - 计算某节点的层次。 - 计算二叉树的宽度。 最后,提供了测试说明及通关代
60 10
|
2月前
|
存储 算法 测试技术
【C++数据结构——树】二叉树的遍历算法(头歌教学实验平台习题) 【合集】
本任务旨在实现二叉树的遍历,包括先序、中序、后序和层次遍历。首先介绍了二叉树的基本概念与结构定义,并通过C++代码示例展示了如何定义二叉树节点及构建二叉树。接着详细讲解了四种遍历方法的递归实现逻辑,以及层次遍历中队列的应用。最后提供了测试用例和预期输出,确保代码正确性。通过这些内容,帮助读者理解并掌握二叉树遍历的核心思想与实现技巧。
61 2
|
2月前
|
数据采集 存储 算法
【C++数据结构——图】图的遍历(头歌教学实验平台习题) 【合集】
本文介绍了图的遍历算法,包括深度优先遍历(DFS)和广度优先遍历(BFS)。深度优先遍历通过递归方式从起始节点深入探索图,适用于寻找路径、拓扑排序等场景;广度优先遍历则按层次逐层访问节点,适合无权图最短路径和网络爬虫等应用。文中提供了C++代码示例,演示了如何实现这两种遍历方法,并附有测试用例及结果,帮助读者理解和实践图的遍历算法。
62 0
|
8月前
|
存储 C++
【C++】二叉树进阶之二叉搜索树(下)
【C++】二叉树进阶之二叉搜索树(下)
45 4
|
8月前
|
Java 编译器 C++
【C++】二叉树进阶之二叉搜索树(上)
【C++】二叉树进阶之二叉搜索树(上)
46 3
|
8月前
|
算法 C++
【C++高阶】高效搜索的秘密:深入解析搜索二叉树
【C++高阶】高效搜索的秘密:深入解析搜索二叉树
60 2
|
8月前
|
存储 算法 搜索推荐
|
9月前
|
算法 搜索推荐 C++
C++之STL常用算法(遍历、查找、排序、拷贝、替换、算数生成、集合)
C++之STL常用算法(遍历、查找、排序、拷贝、替换、算数生成、集合)
|
23天前
|
编译器 C++ 开发者
【C++篇】深度解析类与对象(下)
在上一篇博客中,我们学习了C++的基础类与对象概念,包括类的定义、对象的使用和构造函数的作用。在这一篇,我们将深入探讨C++类的一些重要特性,如构造函数的高级用法、类型转换、static成员、友元、内部类、匿名对象,以及对象拷贝优化等。这些内容可以帮助你更好地理解和应用面向对象编程的核心理念,提升代码的健壮性、灵活性和可维护性。