树是一种非常常见的数据结构,它模拟了自然界中树的结构,由节点(或称为顶点)组成,并且具有层次化的组织形式。树结构在计算机科学中广泛应用,例如在组织数据、管理信息层次以及算法设计中。
const treeObj = {
queryScope: function(tree, func) { //广度优先遍历(循环实现)
let node, list = [...tree]
while (node = list.shift()) {
func(node)
node.children && list.push(...node.children)
}
},
queryDepFirst: function(tree, func) { //深度优先-先序遍历(递归实现)
tree.forEach(data => {
func(data)
data.children && this.queryDepFirst(data.children, func)
})
},
queryDepAfter: function(tree, func) { //深度优先-后序遍历(递归实现)
tree.forEach(data => {
data.children && this.queryDepAfter(data.children, func)
func(data)
})
},
listTo: function(list) { //列表转为树(循环实现)
let info = list.reduce((map, node) => (map[node.id] = node, node.children = [], map), {})
return list.filter(node => {
info[node.parentId] && info[node.parentId].children.push(node)
return !node.parentId
})
},
toList: function(tree) { //树转列表(循环实现)
let node, result = tree.map(node => (node.level = 1, node))
for (let i = 0; i < result.length; i++) {
if (!result[i].children) continue
let list = result[i].children.map(node => (node.level = result[i].level + 1, node))
result.splice(i + 1, 0, ...list)
}
return result
},
filter: function(tree, func) { //树过滤(递归实现):树结构过滤即保留某些符合条件的节点,剪裁掉其它节点
return tree.map(node => ({
...node
})).filter(node => {
node.children = node.children && this.filter(node.children, func)
return func(node) || (node.children && node.children.length)
})
},
find: function(tree, func) { //查找节点(递归实现):遍历到满足条件的节点则返回,遍历完成未找到则返回null
for (const data of tree) {
if (func(data)) return data
if (data.children) {
const res = this.find(data.children, func)
if (res) return res
}
}
return null
},
findPath: function(tree, func, path = []) { //查找节点路径(递归实现)
if (!tree) return []
for (const data of tree) {
path.push(data.id)
if (func(data)) return path
if (data.children) {
const findChildren = this.findPath(data.children, func, path)
if (findChildren.length) return findChildren
}
path.pop()
}
return []
},
findMorePath: function(tree, func, path = [], result = []) { //查找多条节点路径(递归实现)
for (const data of tree) {
path.push(data.id)
func(data) && result.push([...path])
data.children && this.findMorePath(data.children, func, path, result)
path.pop()
}
return result
},
}
示例使用:
let tree = [
{id: '1',name: '节点1',children: [
{id: '1-1',name: '节点1-1'},
{id: '1-2',name: '节点1-2'}
]
},
{id: '2',name: '节点2',children: [
{id: '2-1',name: '节点2-1'}
]
}
]
treeObj.queryScope(tree, node => { console.log(node.name) });//广度优先遍历
/*节点1
节点2
节点1-1
节点1-2
节点2-1*/
treeObj.queryDepFirst(tree, node => { console.log(node.name) });//深度优先-先序遍历
/*节点1
节点1-1
节点1-2
节点2
节点2-1*/
treeObj.queryDepAfter(tree, node => { console.log(node.name) });//深度优先-后序遍历
/*节点1-1
节点1-2
节点1
节点2-1
节点2*/
treeObj.toList(tree);//树转列表
let list = [
{id: '1', name: '节点1',parentId: '',},
{id: '1-1',name: '节点1-1',parentId: '1'},
{id: '1-2',name: '节点1-2',parentId: '1'},
{id: '2',name: '节点2',parentId: ''},
{id: '2-1',name: '节点2-1',parentId: '2'}
]
treeObj.listTo(list);//列表转树(列表必须字段:parentID)
treeObj.findPath(tree, node => node.id === '2-1');//查找节点路径
/*['2', '2-1']*/