找出二叉树所有路径(多种方法)

如标题所示,需要找出二叉树的所有的路径!看下图:
在这里插入图片描述
上图是一个完全二叉树!找出此树的所有的路径!我们来试着想下常用的方法? 首先深度优先遍历(可以用递归,也可以用栈的思想),也可以用广度优先遍历(也可以用队列的思想),那么我们来试下每种方法的实现!下面是模拟的测试数据!

模拟的数据:

let tree = {
    "val": 1,
    "left": {
        "val": 2,
        "left": {
            "val": 4,
            "left": {
                "val": 8
            },
            "right": {
                "val": 9
            }
        },
        "right": {
            "val": 5
        }
    },
    "right": {
        "val": 3,
        "left": {
            "val": 6
        },
        "right": {
            "val": 7
        }
    }
};

一 .深度优先遍历

1.递归方法

其实用递归的话,主要找到基线条件和递归条件就行,否则将会进入死循环!那么什么时候不需要递归了呢,那就是找到叶子结点(下面没有任何子结点),此路径就是一个完整的路径!如果找到的不是叶子结点,那就继续遍历改结点的每个孩子结点!

let findTreePath = (tree) => {
    let pathArrs = [];//保存所有路径的数组
    let map = (tree, pathArr) => {
        if (tree) {
            pathArr.push(tree.val);
            if (!tree.left && !tree.right) {
                pathArrs.push(pathArr);
            } else {
                map(tree.left, [...pathArr]);//这里需要深拷贝下pathArr
                map(tree.right, pathArr);
            };
        };
    };
    map(tree, []);
    return pathArrs;
};
console.log(findTreePath(tree));

在这里插入图片描述

2.栈的思想

先说下思路,首先遍历出左侧树,然后将左侧节点一个一个放进栈中,取出栈中的最后节点(叶子节点),拼接成路径加入到答案中,然后最后个节点出栈,接着判断最后个节点是不是叶子节点,不是的话,接着遍历右侧树节点然后放入栈中,直到找到叶子节点,拼接成路径加入到答案中,如果是的话,直接拼接成路径加入到答案中,说的不是很清楚,看下面的代码,注释写的很清楚!

let findTreePath = (tree) => {
    let stack = [];//存放栈的数组
    let pathArrs = [];//存放多条路径的数组
    let rightArr = [];//存放右侧节点的数组,防止重复遍历
    while (stack.length > 0 || tree) {
        while (tree) {
            stack.push(tree); //将左侧的结点放入栈中
            tree = tree.left; 
        };
        var node = stack[stack.length - 1]; //取栈中最后一个元素
        if (node.right && !rightArr.includes(node.right)) { //往右子树找,防止重复访问
            rightArr.push(node.right);
            tree = node.right;//往右子树开始找
        } else {
            if (!node.right && !node.left) {//判断是否为叶子节点
                var pathArr = [];
                stack.map(p => {
                    pathArr.push(p.val); //拼接路径
                });
                pathArrs.push(pathArr); //存放得到的路径
            };
            stack.pop();//最后个元素出栈
        };
    }
    return pathArrs;
};
console.log(findTreePath(tree));

在这里插入图片描述

二 .广度优先遍历

我们也可以用广度优先搜索来实现。我们维护一个队列,存储节点以及根到该节点的路径。一开始这个队列里只有根节点。在每一步迭代中,我们取出队列中的首节点,如果它是叶子节点,则将它对应的路径加入到答案中。如果它不是叶子节点,则将它的所有孩子节点加入到队列的末尾。当队列为空时广度优先搜索结束,我们即能得到答案

let findTreePath  = function (root) {
     const paths = [];//答案数组
     if (root === null) {
         return paths;
     }
     const node_queue = [root];
     const path_queue = [
         [root.val]
     ];
     while (node_queue.length) {
         const node = node_queue.shift();//取出队列第一个节点
         const path = path_queue.shift();//取出队列第一个路径
         if (!node.left && !node.right) {
             paths.push(path);//是叶子节点放入答案中
         } else {
             if (node.left !== null) {
                 const pathCopy = [...path];//复制一份数组
                 pathCopy.push(node.left.val);//拼接路径
                 node_queue.push(node.left);//把子节点放入队列中
                 path_queue.push(pathCopy);//把拼接好的路径放入队列中
             }
             if (node.right !== null) {
                 const pathCopy = [...path];//复制一份数组
                 pathCopy.push(node.right.val);//拼接路径
                 node_queue.push(node.right);//把子节点放入队列中
                 path_queue.push(pathCopy);//把拼接好的路径放入队列中
             }
         }
     };
     return paths;//返回最终的答案(所有的路径)
 };
 console.log(findTreePath (tree));

在这里插入图片描述

  • 5
    点赞
  • 24
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值