非递归实现二叉树前、中、后序遍历

目录

前序遍历——根左右

思路

代码 

中序遍历——左根右

思路

代码 

后序遍历——左右根

思路

代码


递归遍历相当于隐式的维护了一个栈,而非递归遍历则是模拟这个栈的实现。

力扣(LeetCode)官网 - 全球极客挚爱的技术成长平台

力扣(LeetCode)官网 - 全球极客挚爱的技术成长平台

力扣(LeetCode)官网 - 全球极客挚爱的技术成长平台


前序遍历——根左右

思路

1.左路节点入栈,访问左路节点

2.访问左路节点的右子树

代码 
 vector<int> preorderTraversal(TreeNode* root) {
        stack<TreeNode*> st;
        vector<int> ans;
        TreeNode* cur=root;
        while(!st.empty()||cur!=nullptr)
        {
            //1.访问左路节点,左路节点入栈,后续依次访问左路节点的右子树
            while(cur!=nullptr)
            {
                ans.push_back(cur->val);
                st.push(cur);
                cur=cur->left;
            }

            
            //2.依次访问左路节点的右子树
            TreeNode* top=st.top();
            st.pop();//已经访问过的根节点pop,避免重复访问

            cur=top->right;//用子问题的方法访问右子树

        }
        return ans;

中序遍历——左根右

思路

1.左路节点入栈

2.访问左路节点及其右子树

与前序遍历大致相同,但是左路节点的访问时间不一样。

前序的时候是在入栈的时候访问,中序是取出时访问。

本质

从栈顶取到一个节点,说明这个节点的左子树已经访问完了,

只需要访问它,在访问它的右子树。

代码 
 vector<int> inorderTraversal(TreeNode* root) {
        stack<TreeNode*> st;
        vector<int> ans;
        TreeNode* cur=root;
        while(!st.empty()||cur!=nullptr)
        {
            //1.不访问左路节点,左路节点入栈
            while(cur!=nullptr)
            {
                st.push(cur);
                cur=cur->left;
            }

            
            //2.依次访问左路节点及其右子树
            TreeNode* top=st.top();
            st.pop();

            ans.push_back(top->val);//访问左路节点
            cur=top->right//访问右子树

        }
        return ans;
    }


后序遍历——左右根

思路

与中序遍历相似,只是右子树的访问时间不同。

本质

从栈顶取到一个节点,说明这个节点的左子树已经访问完了,

只需要访问它的右子树,再访问它。

但是这会出现一个节点访问两次的情况,如下图所示:

为了实现不同情况下指向该节点时实现的不同操作,我们引入一个指针prev,该指针始终指向访问(即push到ans)的上一个节点。

具体流程如下

代码
vector<int> postorderTraversal(TreeNode* root) {
        stack<TreeNode*> st;
        vector<int> ans;
        TreeNode* cur=root;
        TreeNode* prev=nullptr;
        while(!st.empty()||cur!=nullptr)
        {
            //1.不访问左路节点,左路节点入栈
            while(cur!=nullptr)
            {
                st.push(cur);
                cur=cur->left;
            }
            //2.依次访问左路节点及其右子树
            TreeNode* top=st.top();

            //右子树访问完了 或
            //上一个访问的节点是是右子树,
            //那么访问该节点并出栈
            if(top->right==nullptr||top->right==prev)
            {
                prev=top;
                ans.push_back(top->val);
                st.pop();
            }
            //继续访问该节点的右子树
            else
            {
                cur=top->right;
            }
            
        }
        return ans;
    }
  • 2
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值