运用DFS算法清除断层节点
业务需求:
返回给第三方目录列表,需根据用户权限显示多层级目录列表
有断层情况;
如:a->b->c->d a为顶级文件夹 依次为子集,子子集…
对于c目录 用户没有权限 则不应有c、d数据
目前可根据父级id查出所有子集目录 为 nodes ,父ID为 parentId
import com.google.common.collect.Lists;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
/**
* 树形结构清理器
* @desc 根据父节点清理断层节点 O(n)
*/
public class TreeCleaner {
public static List<FileVO> removeDisconnectedNodes(List<FileVO> nodes, String parentId) {
// 构建 ID 到节点的映射
Map<String, FileVO> nodeMap = new HashMap<>();
for (FileVO node : nodes) {
nodeMap.put(node.getFileId(), node);
}
// 构建 parentId 到子节点的映射
Map<String, List<FileVO>> parentMap = new HashMap<>();
for (FileVO node : nodes) {
parentMap.computeIfAbsent(node.getParentFileId(), k -> new ArrayList<>()).add(node);
}
// 结果列表
List<FileVO> result = new ArrayList<>();
// 调用方法构建有效的子树(以传入的父ID为根)
buildValidSubtree(parentId, parentMap, nodeMap, result);
return result;
}
private static void buildValidSubtree(String currentId, Map<String, List<FileVO>> parentMap,
Map<String, FileVO> nodeMap, List<FileVO> result) {
// 添加当前节点到结果中
if (nodeMap.containsKey(currentId)) {
result.add(nodeMap.get(currentId));
}
// 获取当前节点的子节点
List<FileVO> children = parentMap.get(currentId);
if (children!= null) {
for (FileVO child : children) {
// 递归构建有效的子树
buildValidSubtree(child.getFileId(), parentMap, nodeMap, result);
}
}
}
public static void main(String[] args) {
// 示例数据
FileVO fileVO = new FileVO();// 根节点
fileVO.setFileId("1");
fileVO.setParentFileId("0");
FileVO fileVO1 = new FileVO();// 根节点
fileVO1.setFileId("2");
fileVO1.setParentFileId("0");
FileVO fileVO2 = new FileVO();// 根节点
fileVO2.setFileId("3");
fileVO2.setParentFileId("1");
FileVO fileVO34 = new FileVO();// 根节点
fileVO34.setFileId("4");
fileVO34.setParentFileId("2");
FileVO fileVO4 = new FileVO();// 根节点
fileVO4.setFileId("5");
fileVO4.setParentFileId("4");
FileVO fileVO5 = new FileVO();// 断层节点
fileVO5.setFileId("6");
fileVO5.setParentFileId("4");
List<FileVO> nodes = Lists.newArrayList(
fileVO, fileVO1, fileVO2, fileVO34, fileVO4, fileVO5
);
// 根据根节点 ID 删除断层节点
List<FileVO> cleanedTree = removeDisconnectedNodes(nodes, "1");
// 打印结果
for (FileVO node : cleanedTree) {
System.out.println("Node ID: " + node.getFileId() + ", Parent ID: " + node.getParentFileId());
}
}
}