C++实现二叉树非递归遍历算法详解

 更新时间:2023年04月23日 09:14:48   作者:命由己造~  
在C++中,二叉树非递归遍历是一种常用的算法,可避免递归过程中的系统开销和栈溢出问题。非递归遍历算法利用栈数据结构实现,可以实现前序、中序和后序遍历,是C++程序员必备技能之一

一、二叉树的前序遍历

题目链接

我们可以把任何一棵树看成左路节点,左路节点和右子树。先访问左路节点,再访问左路节点的右子树。在右子树中也重复这种循环,就是非递归遍历二叉树的思想。

解释:

栈st存放节点,v存放数值,cur初始化为root。

循环条件是栈不为空或者cur不为空(访问最后一个节点之前栈就已经为空了),循环遍历左子树并且把左子树入栈,同时把值存入v中。然后弹出栈顶元素,并且把栈顶元素的右子树赋值给cur,这样就形成了遍历。

当栈不为空的时候说明还有左路节点的右子树没有被访问,当cur不为空的时候说明还有树要被访问。当同时为空的时候才是访问完成。当一个节点出栈的时候说明此时该节点及该节点的左子树已经被访问完成了。

class Solution {
public:
    vector<int> preorderTraversal(TreeNode* root) {
        stack<TreeNode*> st;
        vector<int> v;
        TreeNode* cur = root;
        while(cur || !st.empty())
        {
            while(cur)
            {
                st.push(cur);
                v.push_back(cur->val);
                cur = cur->left;
            }
            TreeNode* node = st.top();
            st.pop();
            cur = node->right;// 转化成子问题访问右子树
        }
        return v;
    }
};

二、二叉树的中序遍历

题目链接

因为中序遍历的访问顺序是左根右,跟前序遍历不同,所以我们让左节点入栈的时候先不访问,出栈(说明左子树访问完了)时在访问节点。

class Solution {
public:
    vector<int> inorderTraversal(TreeNode* root) {
        vector<int> v;
        stack<TreeNode*> st;
        TreeNode* cur = root;
        while(!st.empty() || cur)
        {
            while(cur)
            {
                st.push(cur);
                cur = cur->left;
            }
            TreeNode* node = st.top();
            st.pop();
            v.push_back(node->val);
            cur = node->right;
        }
        return v;
    }
};

三、二叉树的后序遍历

3.1 方法一

首先我们知道后序遍历就是左右根,而我们可以把访问顺序变成根右左,然后再逆置顺序。而根右左就跟前序遍历的方法一样:

class Solution {
public:
    vector<int> postorderTraversal(TreeNode* root) {
        stack<TreeNode*> st;
        vector<int> v;
        TreeNode* cur = root;
        while(cur || !st.empty())
        {
            while(cur)
            {
                st.push(cur);
                v.push_back(cur->val);
                cur = cur->right;
            }
            TreeNode* node = st.top();
            st.pop();
            cur = node->left;
        }
        reverse(v.begin(), v.end());
        return v;
    }
};

3.2 方法二

按照常规的遍历方法走左右根,但是这里有一个问题:

当访问到根的时候有两种情况:

1️⃣ 从左子树回来,现在要先访问右子树

2️⃣ 从右子树回来,左右子树已经访问完毕,再访问根。

针对这种情况我们可以在加一个变量来确定是第几次访问根,如果是第一次就访问右子树,如果是第二次就访问。

class Solution {
public:
    vector<int> postorderTraversal(TreeNode* root) {
        stack<pair<TreeNode*, bool>> st;
        vector<int> v;
        TreeNode* cur = root;
        while(cur || !st.empty())
        {
            while(cur)
            {
                st.push(make_pair(cur, false));
                cur = cur->left;
            }
            TreeNode* node = st.top().first;
            if(st.top().second == true)
            {
                st.pop();
                v.push_back(node->val);
            }
            else
            {
                st.top().second = true;
                cur = node->right;
            }
        }
        return v;
    }
};

到此这篇关于C++实现二叉树非递归遍历算法详解的文章就介绍到这了,更多相关C++二叉树非递归遍历内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

相关文章

  • Cocos2d-x UI开发之CCControlButton控件类实例

    Cocos2d-x UI开发之CCControlButton控件类实例

    这篇文章主要介绍了Cocos2d-x UI开发之CCControlButton控件类实例,本文代码中包含大量注释来讲解CCControlButton控件类的使用,需要的朋友可以参考下
    2014-09-09
  • C/C++编译报错printf was not declared in this scope问题及解决

    C/C++编译报错printf was not declared in 

    这篇文章主要介绍了C/C++编译报错printf was not declared in this scope问题及解决方案,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教
    2023-08-08
  • 详解C语言中strpbrk()函数的用法

    详解C语言中strpbrk()函数的用法

    这篇文章主要介绍了详解C语言中strpbrk()函数的用法,是C语言入门学习中的基础知识,需要的朋友可以参考下
    2015-08-08
  • 详解C++ sizeof(上)

    详解C++ sizeof(上)

    这篇文章主要介绍了C++ sizeof的相关资料,帮助大家更好的理解和学习c++,感兴趣的朋友可以了解下
    2020-08-08
  • C++模拟实现string类的实例代码

    C++模拟实现string类的实例代码

    这篇文章主要给大家介绍了C++如何模拟实现string类,文章通过代码示例讲解的非常详细,有完整的实现过程,具有一定的参考价值,需要的朋友可以参考下
    2023-08-08
  • C语言运算符的重载详解

    C语言运算符的重载详解

    这篇文章主要为大家详细介绍C语言运算符的重载,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下,希望能够给你带来帮助
    2022-02-02
  • C++ 使用PrintWindow实现窗口截图功能

    C++ 使用PrintWindow实现窗口截图功能

    这篇文章主要介绍了C++ 如何使用PrintWindow实现窗口截图功能,文中示例代码非常详细,帮助大家更好的理解和学习,感兴趣的朋友可以了解下
    2020-08-08
  • Libevent的使用及reactor模型详解

    Libevent的使用及reactor模型详解

    Libevent 是一个用C语言编写的、轻量级的开源高性能事件通知库,主要有以下几个亮点:事件驱动( event-driven),高性能;轻量级,专注于网络,这篇文章主要介绍了Libevent的使用及reactor模型,需要的朋友可以参考下
    2024-03-03
  • C++返回值类型后置实现(跟踪返回值类型)

    C++返回值类型后置实现(跟踪返回值类型)

    本文主要介绍了C++返回值类型后置实现,文中通过示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2021-08-08
  • C++另辟蹊径计算1到n的和

    C++另辟蹊径计算1到n的和

    从1加到100,高斯的故事,我们学过。今天,我们写一个程序来试试。首先,用笨方法。一个数一个数的加,我们一般人就是这样干的吗。在计算机程序里面,怎么办呢?1我们把求和的功能写成一个可以针对不同的N运用的,C++里面叫函数
    2023-02-02

最新评论