详细介绍js实现二叉树非递归遍历算法(前序、中序、后序、层序、路径)

目录

一、前序遍历

二、中序遍历

三、后序遍历

四、层序遍历

五、路径遍历


之前参加一家公司面试被问到二叉树的相关非递归遍历算法,顿时懵逼,只记得递归算法的我瑟瑟发抖,下来之后就作了不少的功课。接下来要分享的,都是我经过对比之后选择的较为简单的非递归遍历方法,使用js语言。如有不足,还望指教。

假设一棵二叉树的结构为

详细介绍js实现二叉树非递归遍历算法(前序、中序、后序、层序、路径)_第1张图片

一、前序遍历

使用栈的数据结构。初始化一个栈数组和结果数组

1.将根节点放入栈中, 栈:[1]

2.取出栈顶的节点,将其放入结果数组中, 结果数组: [1],栈: []

3.将取出的节点的右节点放入栈中, 栈: [3]

4.将取出的节点的左节点放入栈中,栈:[3,2]

5.回到步骤2(循环步骤2-4,直到栈为空)取出栈顶节点,将其放入结果数组中,结果数组:[1,2],  栈:[3]

6.将取出的节点的右节点放入栈中, 栈: [3,5]

7.将取出的节点的左节点放入栈中,栈: [3,5,4]

8.回到步骤2....

最后得到结果数组[1,2,4,5,3,6,7]

var preorderTraversal = function(root) {
    let nodestack = [];
    let res = [];
    nodestack.push(root);
    if(root===null){
        return [];
    }
    while(nodestack.length>0){
        let node = nodestack.pop();
        res.push(node.val);
        if(node.right){
            nodestack.push(node.right);
        }
        if(node.left){
            nodestack.push(node.left);
        }
    }
    return res;
};

二、中序遍历

使用栈的数据结构。初始化一个栈数组和结果数组。

1.把根节点放入栈中,然后将根节点重新赋值为根节点的左节点,直到根节点为空。栈: [1,2,4],root = null

2.取出栈顶节点,并将其赋值为根节点,然后将其值放入结果数组,结果数组: [4],栈: [1,2], root = 4

3.将根节点赋值为根节点的的右节点,root = null

4.回到第一步,因为root已经为null,直接到第二步

5.取出栈顶节点,并将其赋值为根节点,然后将其值放入结果数组,结果数组: [4,2],栈: [1], root = 2

6.将根节点赋值为根节点的右节点,root = 5

7.回到步骤1....

最后的结果数组为[4,2,5,1,6,3,7]

var inorderTraversal = function(root) {
    let nodestack = [];
    let res = [];
    if(root===null){
       return [];
    }
    while(root!==null||nodestack.length>0){
        while(root!==null){
            nodestack.push(root);
            root = root.left;
        }
        root = nodestack.pop();
        res.push(root.val);
        root=root.right;
    }
    return res;
};

三、后序遍历

后序遍历的思路很妙,事实上只需要记住,后序遍历就是与前序遍历的完全相反的算法。

1.将根节点放入栈中,栈: [1]

2.取出栈顶的节点,将其从左边插入结果数组,结果数组:[1],栈:[]

3.将取出的节点的左节点放入栈,栈:[2]

4.将取出的节点的右节点放入栈,栈:   [2,3]

5.回到步骤2,取出栈顶的节点,将其从左边插入结果数组,结果数组:[3,1],栈:[2]

6.将取出的节点的左节点放入栈,栈:[2,6]

7.将取出的节点的右节点放入栈,栈: [2,6,7]

8.回到步骤2,取出栈顶的节点,将其从左边插入结果数组,结果数组:[7,3,1],栈:[2,6]

9. .....

最后的结果数组:[4,5,2,6,7,3,1]

var postorderTraversal = function(root) {
    let nodestack = [];
    let res = [];
    if(root===null){
        return [];
    }
    nodestack.push(root);
    while(nodestack.length>0){
        let node = nodestack.pop();
        res.unshift(node.val);
        if(node.left){
            nodestack.push(node.left);
        }
        if(node.right){
            nodestack.push(node.right);
        }
    }
    return res;
};

四、层序遍历

使用了队列的数据结构,遍历得到每一层的节点。

1.将根节点放入队列,使层数初始化为第0层,队列: [1],level: 0

2.将遍历队列,将队列中的节点取出,放入结果数组索引为层数的数组中,并将节点的左节点和右节点放入队列,结果数组:[[1]],  队列: [2,3]

3. 层数加一,level: 1

4.回到步骤2,遍历队列,将队列中的节点取出,放入结果数组索引为层数的数组中,并将节点的左节点和右节点放入队列,结果数组:[[1],[2,3]],  队列: [4,5,6,7]

5.层数加一,level: 2

6.回到步骤2,遍历队列,将队列中的节点取出,放入结果数组索引为层数的数组中,并将节点的左节点和右节点放入队列,结果数组:[[1],[2,3], [4,5,6,7]],  队列: []

7.队列为空,循环结束,结果数组为[[1],[2,3], [4,5,6,7]]

var levelOrder = function(root) {
    let nodequeue = [];
    let res = [];
    if(root===null){
        return [];
    }
    nodequeue.push(root);
    let level = 0;
    while(nodequeue.length>0){
        res[level] = [];
        let len = nodequeue.length;
        for(let i=0;i

五、路径遍历

使用了两个栈,一个节点栈、一个路径栈

1.将根节点放入节点栈,根节点的值放入路径栈, 节点栈:[1],路径栈:[1]

2.将节点栈栈顶的节点取出赋值给node,将路径栈栈顶的值取出赋值给path ,node: 1,  path: 1

3.如果node节点为叶子节点,则将path从左边插入结果数组。

4.将node的左节点放入节点栈,将path+"->"+node的左节点值放入路径栈,节点栈:  [2],  路径栈:[1, 1->2]

5.将node的右节点放入节点栈,将path+"->"+node的右节点值放入路径栈,节点栈:  [2,3],  路径栈:[1, 1->2,1->3]

6.回到步骤2,将节点栈栈顶的节点取出赋值给node,将路径栈栈顶的值取出赋值给path ,node: 3,  path: 1->3

7.如果node节点为叶子节点,则将path从左边插入结果数组。

8.将node的左节点放入节点栈,将path+"->"+node的左节点值放入路径栈,节点栈:  [2, 6],  路径栈:[1, 1->2, 1->3->6]

9.将node的右节点放入节点栈,将path+"->"+node的右节点值放入路径栈,节点栈:  [2, 6, 7],  路径栈:[1, 1->2, 1->3->6, 1->3->7]

10,回到步骤2,将节点栈栈顶的节点取出赋值给node,将路径栈栈顶的值取出赋值给path ,node: 7,  path: 1->3->7

11.此时node节点为叶子节点,将path从左边插入结果数组,结果数组:[1->3->7]

12.......

最后结果数组为[1->2->4, 1->2->5, 1->3->6,1->3->7]

var binaryTreePaths = function(root) {
    var nodestack = [];
    var res = [];
    var pathstack = [];
    if(root===null){
        return res;
    }
    nodestack.push(root);
    pathstack.push(root.val.toString());
    while(nodestack.length>0){
        let node = nodestack.pop();
        let path = pathstack.pop();
        if(node.left===null&&node.right===null){
            res.unshift(path);
        }
        if(node.left){
            nodestack.push(node.left);
            pathstack.push(path+"->"+node.left.val);
        }
        if(node.right){
            nodestack.push(node.right);
            pathstack.push(path+"->"+node.right.val);
        }
    }
    return res;
};

 

你可能感兴趣的:(详细介绍js实现二叉树非递归遍历算法(前序、中序、后序、层序、路径))