【每日一题】二叉树的非递归遍历

二叉树的递归绝对算不上难,但是非递归就要难一些,我们分别来看一看如何非递归进行前中后序遍历。

在这里插入图片描述

说在前边:

题目链接:
前序
中序
后序

我们需要借助栈以及我们会以同一种大思路进行遍历,方便理解。

这种大思路就是先将左路节点入栈,找右子树
细节无非就是将栈中元素弹出与将二叉树的元素压入vector的时机不同

二叉树的前序遍历:

思路:

在这里插入图片描述

代码实现:

/**
 * Definition for a binary tree node.
 * struct TreeNode {
 *     int val;
 *     TreeNode *left;
 *     TreeNode *right;
 *     TreeNode() : val(0), left(nullptr), right(nullptr) {}
 *     TreeNode(int x) : val(x), left(nullptr), right(nullptr) {}
 *     TreeNode(int x, TreeNode *left, TreeNode *right) : val(x), left(left), right(right) {}
 * };
 */
class Solution {
public:
    vector<int> preorderTraversal(TreeNode* root) {
        typedef TreeNode Node;
        Node* cur = root;
        vector<int> ret;
        stack<Node*> st;
        while(cur)
        {
            // 压入左路节点
            while(cur)
            {
                st.push(cur);
                ret.push_back(cur->val);
                cur = cur->left;
            }
            // 寻找右子树
            while(!st.empty())
            {
                Node* top = st.top();
                st.pop();
                if(top->right)
                {
                    cur = top->right;
                    break;
                }
            }
        }
        return ret;
    }
};

这里的代码实现也是有一些细节的,首先对于压入左路节点没什么好说的,
重点是寻找右子树,我们的判断条件是栈是否为空,也就是说,我们的寻找右子树的这个循环有两种结束方式,
其一是找到了右子树,其二是当前栈中节点都没有右子树,当找到右子树我们重复步骤,否则就代表完成遍历了


二叉树的中序遍历:

思路:

中序与前序一致,注意:此时是在栈pop时进行压入节点。

代码实现:

/**
 * Definition for a binary tree node.
 * struct TreeNode {
 *     int val;
 *     TreeNode *left;
 *     TreeNode *right;
 *     TreeNode() : val(0), left(nullptr), right(nullptr) {}
 *     TreeNode(int x) : val(x), left(nullptr), right(nullptr) {}
 *     TreeNode(int x, TreeNode *left, TreeNode *right) : val(x), left(left), right(right) {}
 * };
 */
class Solution {
public:
    vector<int> inorderTraversal(TreeNode* root) {
        typedef TreeNode Node;
        Node* cur = root;
        vector<int> ret;
        stack<Node*> st;
        while(cur)
        {
            // 压入左路节点
            while(cur)
            {
                st.push(cur);
                cur = cur->left;
            }
            // 寻找右子树
            while(!st.empty())
            {
                Node* top = st.top();
                ret.push_back(top->val);
                st.pop();
                if(top->right)
                {
                    cur = top->right;
                    break;
                }
            }
        }
        return ret;
    }
};

二叉树的后序遍历:

后序的细节多了一丢丢,但是无伤大雅

思路:

在这里插入图片描述

代码实现:

/**
 * Definition for a binary tree node.
 * struct TreeNode {
 *     int val;
 *     TreeNode *left;
 *     TreeNode *right;
 *     TreeNode() : val(0), left(nullptr), right(nullptr) {}
 *     TreeNode(int x) : val(x), left(nullptr), right(nullptr) {}
 *     TreeNode(int x, TreeNode *left, TreeNode *right) : val(x), left(left), right(right) {}
 * };
 */
class Solution {
public:
    vector<int> postorderTraversal(TreeNode* root) {
        typedef TreeNode Node;
        Node* cur = root;
        vector<int> ret;
        stack<Node*> st;
        Node* tmp = nullptr;
        while(cur)
        {
            while(cur)
            {
                st.push(cur);
                cur = cur->left;
            }
            while(!st.empty())
            {
                Node* top = st.top();
                if(!top->right)
                {
                    st.pop();
                    tmp = top;
                    ret.push_back(top->val);
                }
                else
                {
                    if(top->right == tmp)
                    {
                        ret.push_back(top->val);
                        st.pop();
                        tmp = top;
                    }
                    else
                    {
                        cur = top->right;
                        break;
                    }
                }
            }
        }
        return ret;
    }
};

其实细心的同学也发现,这段代码可以更改的更优雅一些,因为最后一个while循环中有一部分代码被重复利用,可以将这两种情况合二为一,但是不容易理解,但是重点不在于优不优雅,而是我是使用一个临时变量tmp来记录的,进行判断是否遍历过当前节点,可以画图感受一下哦,

更重要的是tmp要定义在最外部,否则每次循环都会更改tmp那可就酿成大祸了。

此篇文章到此为止~

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值