树的两种遍历:DFS & BFS

93 阅读2分钟

在处理树结构的问题时,深度优先遍历(DFS)  和 广度优先遍历(BFS)  是两种常见的搜索方式。它们都可以用来查找树中的目标节点,但由于遍历方式不同,在某些场景下效率也会有所区别。
例如:

Depth-First Search

深度优先遍历会优先深入树的某一条路径到底,再回溯寻找其他路径。它通常使用递归来实现,适合处理“深度”相关的问题,比如最大深度、路径总和、回溯类问题等。

Breadth-First Search

广度优先遍历则是按层级依次向外扩展的方式进行遍历,更符合我们直觉中的“层次遍历”思路。它通常使用**队列(Queue)**来实现。

为什么层次遍历更推荐使用 BFS?

BFS 天生就是一层一层地向外扩展,非常契合“层次遍历”这一场景。当然,DFS 也可以实现层次遍历,但实现逻辑稍微复杂一些。 lc-102

BFS层次遍历

在这里,对于每一层的处理,逻辑就比较清晰
while来处理层,for来处理层内部的数据

var levelOrder = function (root) {
    if (!root) return []
    let res = []
    let queue = [root]
    while (queue.length) {
        let size = queue.length
        let level = []
        for (let i = 0; i < size; ++i) {
            let node = queue.shift()
            level.push(node.val)
            if (node.left) queue.push(node.left)
            if (node.right) queue.push(node.right)
        }
        res.push(level)
    }
    return res
};

DFS层次遍历

在DFS中,来处理层次,这里就需要来判断,当前层与目前的结果数组的大小关系
当当前层 === 结果数组的长度时
说明此时已经探索到了下一层了,而此时res中还没有添加下一层,此时需要push进入一个空数组来存放数据

var levelOrder = function (root) {
    if (!root) return []
    let res = []
    var dfs = function (level, node) {
        if (!node) return
        // 初始化 n 层的数组,便于 push 元素到 n 层的数组里面
        // 第 n 层的时候,res的长度应该为 n
        // 例如第 0 层的时候, res里面的长度就为 0 
        // 第 1 层的时候, [[3]], 此时再push []
        // 就成了 [[3], []], 然后就 res[1].push(9)
        // [[3], [9]]
        if (level === res.length) {
            res.push([])
        }
        res[level].push(node.val)
        dfs(level + 1, node.left)
        dfs(level + 1, node.right)
    }
    dfs(0, root)
    return res
};