JavaScript:树形数据结构遍历--深度优先遍历和广度优先遍历

11人浏览 / 0人评论 / 添加收藏

开发中我们经常会遇到树形数据结构,那我们如何遍历呢?一种是深度优先遍历,一种是广度优先遍历,今天我们就介绍如何进行树形结构的数据遍历。

一、树结构

定义一颗树,JS中常见的树形数据结构如下,children属性对应的是子树

let tree = [
 {
   id: '1',
   name: '节点1',
   children: [
     {
       id: '1-1',
       name: '节点1-1'
     }
   ]
 },
 {
   id: '2',
   name: '节点2',
   children: [
     {
       id: '2-1',
       name: '节点2-1'
     },
     {
       id: '2-2',
       name: '节点2-2',
       children: [
         {
           id: '2-2-1',
           name: '节点2-2-1'
         }
       ]
     }
   ]
 },
 {
   id: '3',
   name: '节点3'
 }
]

二、深度优先遍历(DFS)

1、递归实现 
function treeIterator(tree, func) {
 tree.forEach((node) => {
   func(node)
   node.children && treeIterator(node.children, func)
 })
}
AI运行代码
javascript
实现逻辑简述:定义treeIterator函数,传入tree(树)和func(回调函数)两个参数,遍历tree数组,执行回调函数,如果当前节点存在children,则递归调用。

函数调用验证:调用treeIterator函数,传入上文定义好的树结构数组,打印出每个节点的name值。

treeIterator(tree, (node) => {
 console.log(node.name)
})
AI运行代码
javascript
控制台打印结果如下:

 

2、循环实现
function treeIterator(tree, func) {
 let node, curTree = [...tree]
 while ((node = curTree.shift())) {
   func(node)
   node.children && curTree.unshift(...node.children)
 }
}

实现逻辑简述:

(1)定义node作为当前节点,curTree为传入的树(不影响原数组tree);

(2)执行while循环,curTree数组第一个元素从其中删除,并返回第一个元素赋值给node;

(3)①执行回调函数;②如果当前节点存在子树,则追加到curTree数组的开头,继续执行循环,直到curTree没有元素为止。

函数调用验证:参考上述递归实现验证,方式和结果一致。

三、广度优先遍历(BFS)

function treeIterator(tree, func) {
 let node, curTree = [...tree]
 while ((node = curTree.shift())) {
   func(node)
   node.children && curTree.push(...node.children)
 }
}
AI运行代码
javascript
实现逻辑简述:和上述深度优先遍历的循环实现差不多。区别在于如果当前节点存在子树,则追加到list数组的末尾。

函数调用验证:

treeIterator(tree, (node) => {
 console.log(node.name)
})

控制台打印结果如下:

感谢您读完本文!如果本文对您有帮助,请点个赞呗,您的点赞是对我最大的支持和认可!
 

全部评论