深度优先搜索算法(英语:Depth-First-Search,缩写为DFS)是一种用于遍历或搜索树或图的算法。这个算法会尽可能深地搜索树的分支。当节点v的所在边都己被探寻过,搜索将回溯到发现节点v的那条边的起始节点。这一过程一直进行到已发现从源节点可达的所有节点为止。如果还存在未被发现的节点,则选择其中一个作为源节点并重复以上过程,整个进程反复进行直到所有节点都被访问为止。
本篇将介绍深度优先搜索算法在实战开发中的一个简单应用。
const treeData = [
{
"n": "燃气生产和供应业",
"c": [
{
"n": "燃气生产和供应业",
"c": [
{
"n": "天然气生产和供应业"
},
{
"n": "液化石油气生产和供应业"
},
{
"n": "煤气生产和供应业"
}
]
},
{
"n": "生物质燃气生产和供应业",
"c": [
{
"n": "生物质燃气生产和供应业"
}
]
}
]
},
{
"n": "国际组织",
"c": [
{
"n": "国际组织",
"c": [
{
"n": "国际组织",
"c": [
{
"n": "国际组织"
}
]
}
]
}
]
}
]
根据以上数据,我们需要将数据中 重复的 n 属性值所在的对象 移除,比较不常规的是:如果被移除的对象下有子数据,则需要保留,见下图
实现代码很简单,如下:
function removeDuplicateValues(data: any[]) {
const visited = new Set()
function dfs(tree: any[]) {
for (let i = 0; i < tree.length; i++) {
const treeNode = tree[i]
// 如果节点值已经访问过,表示树结构中有重复节点
if (visited.has(treeNode.n)) {
// 如果该节点有子节点,则保留所有子节点数据
if (treeNode?.c?.length) {
tree.push(...treeNode.c)
}
// 该节点为重复节点,从树结构中删除
tree.splice(i, 1) && i--
} else {
// 标记节点值已经访问过
visited.add(treeNode.n)
// 递归遍历子节点
if (treeNode?.c?.length) {
dfs(treeNode.c)
}
}
}
}
dfs(data)
return data
}
测试一下
const result = removeDuplicateValues(treeData)
console.log('result: ', JSON.stringify(result, null, '\t'));
result: [
{
"n": "燃气生产和供应业",
"c": [
{
"n": "生物质燃气生产和供应业",
"c": []
},
{
"n": "天然气生产和供应业"
},
{
"n": "液化石油气生产和供应业"
},
{
"n": "煤气生产和供应业"
}
]
},
{
"n": "国际组织",
"c": []
}
]
核心的地方就是采用 Set
标记已访问的节点,在对应的条件下执行对应的操作即可。好了,完结!