算法和数据结构:遍历二叉树

100 阅读2分钟

前序遍历

递归

算法递归的方法比较简单,,每次只需要操作当前节点,再先后递归左子节点和右子节点。中序遍历和后序遍历的递归实现,只需要换下3行代码的顺序即可,后面不再给出。

var preorderTraversalNode = function(node, result){
    if(node){
        result.push(node.val)
        preorderTraversalNode(node.left,result)
        preorderTraversalNode(node.right,result)
    }
}

直接调换顺序即可 

使用栈

弹出节点,进行操作,再分别压入其右子节点和左子节点,这样使得下一次弹出的节点会是当前节点的左子节点,满足先序遍历的顺序要求。

var preorderTraversal = function(root) {
    //空检测
    if(!root) return [];

    var result = [];
    var stack = [root],
        current = null;
    while (stack.length !== 0){
        current = stack.pop();
        result.push(current.val);
        current.right && stack.push(current.right);
        current.left && stack.push(current.left);
    }

    return result;
};

中序遍历

中序遍历也是二叉搜索树升序遍历的遍历方法 。

递归

使用栈

先将左边压到底,压到底之后开始出栈,进行操作。然后访问该节点的右分支,进行同样操作。

var inorderTraversal = function(root) {
    if(!root) return [];
    var result = [],
        current = root,
        stack = [];
    while(stack.length !== 0  || current){
        while(current){
            stack.push(current);
            current = current.left;
        }
        current = stack.pop();
        result.push(current.val);
        current = current.right;

    }

    return result;
}

后序遍历

递归

使用栈

这里用了一种取巧的方式,后序遍历是左右中的顺序,其反过来就是中右左,也就是反前序遍历,我们只需要修改一下前序遍历访问左右子节点的顺序,即可得到反前序遍历,然后将遍历的结果 reverse ,就得到后序遍历的结果,神奇不神奇!

const postorderTraversal = function(root) {
    //空检测
    if(!root) return [];
    let result = [];

    var current = null,
        stack = [root];
    while(stack.length != 0){
        current = stack.pop();
        result.push(current.val);
        current.left && stack.push(current.left);
        current.right && stack.push(current.right);
    }
    return result.reverse();
};

层序遍历

层序遍历使用队列实现,每一轮都把同一层的节点全部入列,然后在下一轮中依次出列,每个节点进行操作,然后左右子节点分别入列,这样能保证每一层从左往右的顺序。

以 leetcode 637. 二叉树的层平均值 为例给出代码

var averageOfLevels = function(root) {
    if(!root) return false;

    var que = [root],
        current = null,
        result = [],
        sum = 0;
    while(que.length !== 0){
        let levLength = que.length;
        for(i = 1; i<=levLength; i++){   //这个循环的次数需要固定,因为que.length是变化的
            current = que.shift();
            sum += current.val;
            current.left && que.push(current.left);
            current.right && que.push(current.right);
        }
        result.push(sum/levLength);
        sum = 0;
    }
    return result;
};