二叉树的前,中,后序的非递归实现(c++)

前言

对于二叉树来说,遍历它有多种方式,其中递归遍历是比较简单的,但是非递归的实现就有一定的难度,在这里介绍一种非递归实现二叉树遍历的方式。

1.前序遍历

1.1思路

其实对于二叉树的非递归实现,实际上就是用代码来模拟操作系统压栈和弹栈的过程 。让我们一起来看看吧,首先将一棵树 分为左边节点和左边节点的右子树。如图:

然后借助于一个栈,先将左边节点入栈,入栈时要将节点的值存到数组中。将左边节点全部入栈后,再来将左边节点的右子树入栈,重复上述过程。直至栈为空并且,当前的指针也为空,此时完成二叉树的前序遍历。如图:

1.2代码实现

cpp 复制代码
    vector<int> preorderTraversal(TreeNode* root)
    {
        vector<int> v;
        stack<TreeNode*> sT;
        //1.处理左边节点
        //2.处理左边节点的右子树
        TreeNode * cur = root;
        while(cur ||  !sT.empty()  )
        {
            while(cur)
            {
                //左边节点入栈
                sT.push(cur);
                v.push_back(cur->val);
                
                cur = cur -> left;
            }
            TreeNode* p = sT.top();
            sT.pop();
            cur = p -> right;
            //左边节点的右子树入栈
        }
        return v;
    }

2.中序遍历

2.1思路

中序遍历的思路和前序遍历基本相同,就是此时左边节点入栈时不会将左边节点的val插到数组中,而是在栈中将节点的指针取出时再尾插到数组中。

2.2代码实现

cpp 复制代码
  vector<int> inorderTraversal(TreeNode* root) 
    {
        vector<int> ret;
        stack< TreeNode* > sT;
        TreeNode* cur = root;
        while(cur || !sT.empty())
        {
            //树的左边节点入栈
            while(cur)
            {
                sT.push(cur);
                cur = cur -> left;
            }
            //取出栈顶节点的指针
            //将栈顶节点指针的val尾插到数组中
            TreeNode * top = sT.top();
            sT.pop();
            //左边节点的右子树入栈
            cur = top -> right;
            ret.push_back(top->val);
        }
        return ret;
    }

3.后序遍历

3.1思路

后序遍历沿用了中序遍历的思路,唯一不同的是将左边节点依次入栈后,出栈时先处理当前节点的左子树,然后将右子树入栈,等处理完右子树后再来处理当前节点。

3.2代码实现

cpp 复制代码
    vector<int> postorderTraversal(TreeNode* root) 
    {
        TreeNode * cur = root;
        TreeNode * back = nullptr;//用来记录处理上一个节点
        vector<int> ret;
        stack<TreeNode*> sT;
        while(cur || !sT.empty() )
        {
            //左边节点入栈
            while(cur)
            {
                sT.push(cur);
                cur = cur->left;
            }
            //取出栈顶数据
            TreeNode* top = sT.top();
            
            if(top->right == nullptr || top->right == back)
            {
                ret.push_back(top->val);
                back = top;//记录处理过的节点
                sT.pop();
            }
            else
            {
                //左边节点的右子树入栈
                cur = top -> right;
            }
        }
        return ret;
    }

后续遍历需要注意的是在什么时候来对当前节点进行处理 ,要先处理左右节点之后对当前节点进行处理,如果右节点为空很好办直接判断右节点为不为空就可以了,但是如果右节点不为空呢?怎么确保右节点已经处理过了再来对当前节点进行处理呢,这里提供一种较为简单的思路,通过一个指针来记录上次处理的节点,因为后序遍历总是按照左子树,右子树和根的处理顺序来的所以我们只需要处理比较上一个处理的节点是不是当前节点的右子树就可以知道 当前节点的右子树是否已经被处理过了,来判断当前节点是否需要处理。

讲的不好,希望不要喷我。

相关推荐
kakakahahahaha5 分钟前
Windows C盘临时文件清理:%temp%、Windows Temp、Prefetch、Windows.old与hiberfil.sys处理指南
c语言·开发语言·windows
朝朝辞暮i10 分钟前
C++ 第 27 课:智能指针 shared_ptr
开发语言·c++·算法
by2099931 分钟前
学会使用std::string类,并理解其内部是如何管理字符串的详细阐述(上)
c++·笔记·字符串·类和对象·string
沙漠之主32 分钟前
C++编程教学设计资料:从入门到实战的完整课程方案
java·前端·c++
朝朝辞暮i42 分钟前
C++ 第 29 课:回调函数 Callback
开发语言·c++·算法
笨笨饿1 小时前
140_AI新手村MCP与Skills是干嘛的
开发语言·人工智能·python·stm32·单片机·嵌入式硬件·物联网
YOLO数据集集合1 小时前
EvoAgent:面向PR研发治理的自进化Multi-Agent Harness系统
java·开发语言·目标检测·agent·自进化
kaixin_learn_qt_ing1 小时前
C++多态实现原理
c++
无名猿1 小时前
unique_ptr 完全指南:独占所有权与零开销
c++·性能优化·内存管理·标准库·现代c++
笑鸿的学习笔记2 小时前
C++笔记之大块顺序写
java·c++·笔记