js算法题解(第二十二天)---144.二叉树的前序遍历

129 阅读3分钟

「这是我参与2022首次更文挑战的第23天,活动详情查看:2022首次更文挑战

前言

每天至少一道算法题,死磕算法

本章我们主要梳理二叉树的迭代方法,我们看一下leetcode的第144到题目的最下面那几行字进阶:递归算法很简单,你可以通过迭代算法完成吗?

前几天我讲过层序遍历和队列有关,那么先序遍历这些又和什么有关呢?

可能有的同学已经猜到了,没错就是和栈有关

图片.png

先序遍历其实也就是深度优先遍历,深度优先遍历的特点那就是一杆子打到底,哈哈,比如上图,我们发现A有左子树B,那么A入栈,继续一杆子打到底,发现B有左子树D,继续一杆子打到底,发现没有左子树,那么出栈,出栈的时候看看有没有右子树呢?也没有,返回到了B,B出栈,然后看B有右子树么?有,E入栈,先看E有没有左子树,没有,那E出栈,出来的时候看一下有没有右子树,也没有,那好,返回到A,为什么不是返回B,因为B已经出栈了....

我们可以在总结一下这个思路

题目

这是leetcode上的第144道题目二叉树的前序遍历

给你二叉树的根节点 root ,返回它节点值的 前序遍历。

示例 1:

输入: root = [1,null,2,3]
输出: [1,2,3]

是的,这道题的确用递归很简单

但是遍历算法又该何去何从呢

思路

前序遍历

var preorderTraversal = function(root) {
    // 当前节点
    let cur = root;
    // 深度遍历和栈有关栈
    let stack = [];
    // 结果
    let result = [];
    // 为什么while结束条件是cur||stack.length呢?
    // 因为初始化stack中没有值
    while(cur||stack.length)
        // 左节点一杆子打到底,右节点的话会存一下数据
        while(cur){
            result.push(cur.val);
            stack.push(cur);
            cur=cur.left;
        }
        // 每弹出一个栈,就到达右孩子
        let tmp = stack.pop();
        cur = tmp.right;
    }
    return result;
};

模板解法的思路稍有不同,它先将根节点 cur 和所有的左孩子入栈并加入结果中,直至 cur 为空,用一个 while 循环实现:

image.png

然后,每弹出一个栈顶元素 tmp,就到达它的右孩子,再将这个节点当作 cur 重新按上面的步骤来一遍,直至栈为空。这里又需要一个 while 循环。

当我们写出前序遍历以后,中序遍历也就很好做了,中序遍历和前序遍历最大的区别就是结果打印的时间 前序遍历是开始左节点开始入栈就开始打印,一个是左节点遍历结束,开始出栈才开始打印,

中序遍历

var inorderTraversal = function(root) {
    // 返回的结果
    let result = [];
    // 当前节点
    let cur = root;
    // 深度遍历离不开栈
    let stack = [];
    while(cur||stack.length){
        // 
        while(cur){
            stack.push(cur);
            cur = cur.left;
        }
        let tmp = stack.pop();
        result.push(tmp.val);
        cur = tmp.right;
    }
    return result;
};

后序遍历

后序遍历遍历规则是 左 -> 右 -> 中 。这个顺序相对于先序遍历,最明显的变化就是根结点的位置从第一个变成了倒数第一个。

那么我们直接把打印顺序放到最后一个?

肯定是不可以的,中序是这样放的。 我们看看跟先序遍历的区别一个出栈顺序是中 -> 左 ->右如果把先序遍历写成中 -> 右 -> 左那么反过来不就是后序遍历了么

所以我们写一下

var postorderTraversal = function(root) {
    let result = [];
    let cur = root;
    let stack = [];
    while(cur||stack.length){
        while(cur){
            result.push(cur.val);
            stack.push(cur);
            cur = cur.right;
        }
        let tmp = stack.pop();
        cur = tmp.left;
    }
    return result.reverse();
};

也是很快的就写出来了

参考