【leecode】二叉树的前中后序遍历

本文讲述了作者在学习递归和迭代算法过程中的心得,分享了如何通过口诀记忆前序和后序遍历,以及将递归转化为迭代的方法,强调了LeetCode官方解法的简洁性。中序遍历则涉及到深度优先思想。
摘要由CSDN通过智能技术生成

刷题的时候,这玩意肯定会遇到的,而且一般是初学者的一个大坑。

递归法很简单,迭代法第一次看还看不出个所以然,得看了几次,加上背算法细节,记忆,才可以,理解了再去记忆,几乎不可能,那就死记硬背。。。

我也是这个过程。

今天又重点看了下这个算法,通过别人的讲解有点启发,一下子就写出来三种遍历方法,有了自己的一套方便记忆的方法,算是开窍了。

个人还是比较推荐 leecode 上面的官方解法,不要去迷信什么统一的结构,什么代码随想录上的,个人感觉太复杂了。官方解法比较简洁,但是有点难理解而已。。

总的原则是:

  • 前序后序 结构是相同的,先写出前序,稍微改一下就是后序,所以,只要记忆 前序 即可。
  • 中序 遍历和前后不一样,需要单独记忆

理论

理论上说,如何把递归转化为迭代,常规操作就是使用 stack, stack 的先进后出 的特性天然就拥有递归的性质,也是比较神奇的。所以,后面的算法中都是使用的 stack。

前序遍历:

口诀

口诀:先输出本省,有孩子,先压右边,再压左边
记住口诀就行

vector<int> pre_order(Node *head)
{
    stack<int> st;
    vector<int> res;

    st.push(head);
    while (!st.empty()) {
        // 先输出中间
        Node *node = st.top();
        res.push_back(node->value);
        st.pop();

        // 先压右节点
        if (node->right) {
            st.push(node->right);
        }
        // 再压左节点
        if (node->left) {
            st.push(node->left);
        }
    }

    return res;
}

解释

先输出中间的,很好理解,就是前序遍历嘛
先压右边,再压左边,也很好理解,栈嘛,后压的先出来,也就是 左边的先出来。

后序遍历

口诀

针对 前序改巴改巴就行,几个修改点,记住:

  • 先右再左,改成,先左后右
  • 原来输出的地方,改成输出到一个临时 stack 中,【因为需要逆序一下】
  • 最后,逆序输出 stack 到 res 数组中即可

你说原理是啥,我也搞不懂,反正按照口诀来该就对了。

vector<int> postorderTraversal(TreeNode* root) {
    stack<TreeNode*> st;
    vector<int> res;
    stack<int> tmp;
    TreeNode *node;

    if (!root) {
        return res;
    }

    st.push(root);
    while (!st.empty()) {
        node = st.top();
        // 原先输出的地方,改成输出到一个 临时的 stack 中,为了逆序输出
        //res.push_back(node->val);
        tmp.push(node->val);
        st.pop();

		// 改成,先左后右
        if (node->left) {
            st.push(node->left);
        }
        if (node->right) {
            st.push(node->right);
        }
    }

    int val;
    while (!tmp.empty()) {
        val = tmp.top();
        res.push_back(val);
        tmp.pop();
    }

    return res;
}

解释

没啥好解释的,我也不懂:)

中序遍历

中序遍历是另一套结构了,

口诀

口诀:左边一路走到黑,不断试探右边

感觉就和深度优先的思想差不多了,自己慢慢体会吧,脑子里一直是这张图:
在这里插入图片描述

vector<int> inorderTraversal(TreeNode* root) {
    stack<TreeNode*> st;
    vector<int> res;
    TreeNode* temp;

    temp = root;
    while (temp || !st.empty()) {
        if (temp) {
        	// 左边一路走到底
            st.push(temp);
            temp = temp->left;
        } else {
        	// 走不通了,尝试右边
            TreeNode *node = st.top();
            res.push_back(node->val);
            st.pop();
            temp = node->right;
        }
    }
    return res;
}

解释

其实还是挺容易理解的,左边就深度优先,到底,然后走不通了,退回来,一旦发现右子树有值了,继续在右子树上进行深度优先。

  • 12
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值