LeetCode题解 二叉树(二):二叉树基本概念;使用迭代法求解二叉树的前中后序遍历

二叉树的迭代遍历

上一弹里,我们对如何使用递归算法对二叉树进行遍历做了介绍,写起来非常简单的样子

那么如何使用迭代法求解前序、中序、后序遍历呢?

首先,前序遍历,处理每个结点的顺序应为“根”(指遍历到的当前节点)在最前面,之后跟左孩子和右孩子。

这时候我们会想到一种数据结构,栈。

先把根节点入栈,再入什么呢?是左孩子吗?

如果一棵树只有三个结点[1 2 3],如果先入左孩子2,再入右孩子3,那么两个孩子出栈的顺序就会是先出3,再出2,与前序遍历的顺序不一致。

所以当根节点入栈后,要先入右孩子才行。

前序遍历的递归写法如下:

vector<int> preorderTraversal(TreeNode* root) {
    if (!root) return {};
    stack<TreeNode*> stk;
    vector<int> res;
    stk.push(root);

    while (!stk.empty()) {
        TreeNode *node = stk.top();
        stk.pop();
        res.push_back(node->val);
        if (node->right) stk.push(node->right);
        if (node->left) stk.push(node->left);
    }
    return res;
}

其次,中序遍历,处理节点的顺序应为“左根右”,虽然仅仅换了中间结点的顺序,但是却不能按照前序遍历那么写。

原因也很简单,刚刚前序遍历的时候,每次弹出一个节点,就直接把对应的值保存到结果数组中,但是中序遍历却不能如此。

想一想,中序遍历要先遍历到整个树的底层,再逐层向上处理。并非遇到中间结点就要处理中间结点的值。其遍历结点和处理结点的顺序是不一样的。

中序遍历需要先遍历到整棵树的最左下角,依次把途中遇到的所有节点入栈(判断条件就是结点是否为空,如果是空的话就说明已经遍历到最左下角结点的叶子结点了)

之后应该做什么呢?出栈,然后记录数值,然后遍历其右结点。第一次出栈的是左下角结点,其右孩子是空,那么就继续弹出下一个值,该值为最左下角结点的父结点。

到这里整体逻辑就已经初具雏形了,中序遍历的迭代写法,代码如下:

vector<int> inorderTraversal(TreeNode* root) {
    if (!root) return {};
    stack<TreeNode*> stk;
    vector<int> res;
    TreeNode *cur = root; 
    while (cur || !stk.empty()) {
        if (cur) {
            stk.push(cur);
            cur = cur->left;
        } else {
            cur = stk.top();
            stk.pop();
            res.push_back(cur->val);
            cur = cur->right;
        }
    }
    return res;
}

最后,是后序遍历,顺序是“左右根”,那么写法是不是近似于前序遍历呢?

我们想一想,前序是“根左右”,如果调整一下,变为“根右左”,此时入栈顺序真的就成了先入左孩子,再入右孩子。

将最终结果翻转一下,就成了“左右根”,就是后序遍历的顺序。

所以,后序遍历的迭代写法,代码如下:

vector<int> postorderTraversal(TreeNode* root) {
    if (!root) return {};
    stack<TreeNode*> stk;
    vector<int> res;
    stk.push(root);

    while (!stk.empty()) {
        TreeNode *node = stk.top();
        stk.pop();
        res.push_back(node->val);
        if (node->left) stk.push(node->left);
        if (node->right) stk.push(node->right);
    }
    reverse(res.begin(), res.end());
    return res;
}

这样写其实是有些取巧的,而且翻转增添了时间复杂度,那么有没有直接的后序遍历写法呢?

其实也是有的,而是不仅如此,前中后序的迭代法,还有着一种统一的模板,感谢随想录,这部分的内容就放在下一篇了。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值