二叉树的后序遍历(leetcode 145)

来源:互联网 发布:php门户网站源码 编辑:程序博客网 时间:2024/06/05 15:26

写在前面

关于二叉树的后序遍历,我们通常要说的是它的非递归写法,这一点,网上有很多写法,大概看了一下,基于先前访问结点的算法基本属于主流思想,但大家的写法似乎都不太简洁,有各种各样的问题,这里写一种简单易懂的写法,供参考。

思路分析

1)其实除了层序遍历外,三种方式的遍历都可以看作是递归思想的延续,其中最难的要数后序遍历,因为右子树的访问状态是一个较难处理的点。我们观察发现,左子树访问完成后,下一步是访问右子树,这个时候有几种情况:1.右子树为空 ,这个时候我们直接访问根结点;2 右子树已经访问过了,这个时候的情况与1类似,我们直接访问根结点;3 右子树不为空且未被访问过,这个时候我们就访问右子树,并递归处理。
2)标准库设施。非递归的树的遍历几乎都会用到栈(层序遍历除外),后序遍历也不例外。本题中,我们思路1,2,3的正确性也依赖于栈结构。我们访问过的元素必定是栈顶元素,这一点由栈的特性保证(思考整个的后序遍历过程),此外,我们有一个额外的结点来标记已访问过的元素,与栈顶元素作比较。

代码实现

// 我们用vector保存遍历过的元素 并返回结果

vector<int> postOrder(Node* root) {    stack<Node*> s;    vector<int> retVec;    Node* current = root;    Node* pre = nullptr;    while(!s.empty()||current){        while(current) {        s.push(current);        current = current->left;        }        auto top = s.top();        if(top->right==nullptr||top->right==pre) {            pre = top;            retVec.push_back(top->val);            current = nullptr;            s.pop();        }        else {            current = top->right;        }}return retVec;}

小结

在某位同学的博客上看到一个观点,说要追求代码的极度简洁,我认同简洁的观点,但我认为,可读性仍然是第一位,其次是复杂度,过度追求简洁并不可取。

0 0
原创粉丝点击