企业级组织架构通常呈现为多层级嵌套的节点树结构,每个节点包含部门ID、部门名称、上级部门ID、子部门列表等属性,需要遍历整棵树并抽取符合特定条件的节点时,深度优先搜索配合分支回溯是高效的实现方案。

DFS分支回溯核心原理
深度优先搜索(DFS)的核心逻辑是从根节点出发,优先遍历当前节点的第一个子节点,直到子节点为空或者达到遍历终止条件,再回溯到上一个节点继续遍历其他分支。分支回溯则是在遍历过程中,当进入某个分支后,若需要记录路径或者筛选节点,会在进入分支时记录状态,离开分支时恢复状态,避免状态污染。
针对组织架构节点树的遍历,DFS的优势在于可以完整覆盖所有层级的节点,不会因为层级过深出现遗漏,同时回溯机制可以支持在遍历过程中动态判断节点是否符合抽取条件。
企业组织架构节点定义
首先定义组织架构节点的基础结构,包含节点核心属性和子节点列表:
public class OrgNode {
// 部门ID
private String deptId;
// 部门名称
private String deptName;
// 部门负责人
private String leader;
// 子部门列表
private List<OrgNode> children;
// 构造方法、getter和setter省略
}
DFS遍历并抽取节点的实现步骤
1. 初始化遍历状态
准备存储抽取结果的集合,同时如果需要记录遍历路径,可以初始化一个路径列表,用于回溯时移除已遍历的节点。
2. 递归实现DFS遍历逻辑
递归函数接收当前节点、结果集合、遍历路径三个参数,首先处理当前节点:判断是否符合抽取条件,符合则加入结果集合;然后将当前节点加入遍历路径,递归遍历所有子节点;最后从遍历路径中移除当前节点,完成回溯。
以下是完整的遍历抽取实现代码:
import java.util.ArrayList;
import java.util.List;
public class OrgTreeTraversal {
/**
* 抽取组织架构树中符合条件的节点
* @param root 组织架构根节点
* @param filter 节点筛选条件,返回true表示需要抽取该节点
* @return 符合条件的节点列表
*/
public static List<OrgNode> extractNodes(OrgNode root, NodeFilter filter) {
List<OrgNode> result = new ArrayList<>();
// 从根节点开始遍历
dfs(root, result, filter);
return result;
}
/**
* DFS递归遍历方法
* @param currentNode 当前遍历的节点
* @param result 存储抽取结果的集合
* @param filter 筛选条件
*/
private static void dfs(OrgNode currentNode, List<OrgNode> result, NodeFilter filter) {
if (currentNode == null) {
return;
}
// 判断当前节点是否符合抽取条件
if (filter.match(currentNode)) {
result.add(currentNode);
}
// 获取当前节点的子节点列表
List<OrgNode> children = currentNode.getChildren();
if (children != null && !children.isEmpty()) {
// 遍历所有子节点
for (OrgNode child : children) {
dfs(child, result, filter);
}
}
}
/**
* 节点筛选条件接口
*/
public interface NodeFilter {
/**
* 判断节点是否匹配条件
* @param node 待判断的节点
* @return 匹配返回true,否则返回false
*/
boolean match(OrgNode node);
}
// 示例:抽取所有负责人为张三的部门节点
public static void main(String[] args) {
// 假设已经构建了完整的组织架构树root
OrgNode root = buildOrgTree();
// 定义筛选条件:部门负责人为张三
NodeFilter filter = node -> "张三".equals(node.getLeader());
List<OrgNode> targetNodes = extractNodes(root, filter);
System.out.println("抽取的节点数量:" + targetNodes.size());
for (OrgNode node : targetNodes) {
System.out.println("部门ID:" + node.getDeptId() + ",部门名称:" + node.getDeptName());
}
}
/**
* 构建示例组织架构树的方法
*/
private static OrgNode buildOrgTree() {
OrgNode root = new OrgNode();
root.setDeptId("1");
root.setDeptName("总公司");
root.setLeader("李四");
OrgNode child1 = new OrgNode();
child1.setDeptId("2");
child1.setDeptName("技术部");
child1.setLeader("张三");
OrgNode child2 = new OrgNode();
child2.setDeptId("3");
child2.setDeptName("市场部");
child2.setLeader("王五");
OrgNode grandChild1 = new OrgNode();
grandChild1.setDeptId("4");
grandChild1.setDeptName("前端组");
grandChild1.setLeader("张三");
List<OrgNode> child1Children = new ArrayList<>();
child1Children.add(grandChild1);
child1.setChildren(child1Children);
List<OrgNode> rootChildren = new ArrayList<>();
rootChildren.add(child1);
rootChildren.add(child2);
root.setChildren(rootChildren);
return root;
}
}
非递归方式实现DFS遍历
如果组织架构树的层级过深,递归方式可能会出现栈溢出问题,此时可以使用栈实现非递归的DFS遍历:
import java.util.ArrayDeque;
import java.util.ArrayList;
import java.util.Deque;
import java.util.List;
public class OrgTreeTraversalNonRecursive {
public static List<OrgNode> extractNodes(OrgNode root, NodeFilter filter) {
List<OrgNode> result = new ArrayList<>();
if (root == null) {
return result;
}
// 使用栈存储待遍历的节点
Deque<OrgNode> stack = new ArrayDeque<>();
stack.push(root);
while (!stack.isEmpty()) {
OrgNode currentNode = stack.pop();
// 判断当前节点是否符合条件
if (filter.match(currentNode)) {
result.add(currentNode);
}
// 将子节点逆序入栈,保证遍历顺序和递归一致
List<OrgNode> children = currentNode.getChildren();
if (children != null && !children.isEmpty()) {
for (int i = children.size() - 1; i >= 0; i--) {
stack.push(children.get(i));
}
}
}
return result;
}
public interface NodeFilter {
boolean match(OrgNode node);
}
}
注意事项
- 遍历前需要校验根节点是否为空,避免出现空指针异常。
- 如果组织架构树存在循环引用(如子节点指向父节点),需要增加已访问节点的校验,避免无限遍历。
- 抽取条件如果涉及多维度判断,可以在
NodeFilter接口的实现中扩展逻辑,不需要修改遍历核心代码。 - 若需要记录节点的遍历路径,可以在递归方式中增加路径参数,进入节点时加入路径,回溯时移除路径即可。