
在企业组织架构中,部门之间常常存在层级关系,形成一个树形结构。在java中,我们可以通过接口来抽象这种关系:
import java.util.List;
import java.util.Optional;
import java.util.function.Predicate;
// 部门接口,定义了所有部门的基本属性
public interface Department {
String getName();
String getType();
// 默认方法:检查当前部门是否匹配某个条件
default Optional<Department> getMatchingDepartment(Predicate<Department> predicate) {
if (predicate.test(this)) {
return Optional.of(this);
}
return Optional.empty();
}
}
// 公司接口,继承自部门,并拥有子部门列表,表示它是一个复合部门
public interface Company extends Department {
List<Department> getDepartments();
// 默认方法:尝试在子部门中查找匹配项
// 注意:此实现仅检查直接子部门,且只返回第一个匹配项,不进行深度遍历
default Optional<Department> getMatchingDepartment(Predicate<Department> predicate) {
return getDepartments().stream()
.map(department -> department.getMatchingDepartment(predicate))
.filter(Optional::isPresent)
.map(Optional::get)
.findFirst();
}
}在这个结构中,Company可以包含多个Department,而这些Department又可能是Company(即子公司的概念),从而形成一个多层级的树状结构。我们的目标是,给定一个部门类型(type),在整个组织树中找出所有匹配该类型的所有部门。
在上述Company接口的getMatchingDepartment默认方法中,我们尝试通过流式操作来查找匹配的部门。
public interface Company extends Department {
// ...
default Optional<Department> getMatchingDepartment(Predicate<Department> predicate) {
return getDepartments().stream()
.map(department -> department.getMatchingDepartment(predicate)) // 对每个子部门调用其自身的getMatchingDepartment
.filter(Optional::isPresent)
.map(Optional::get)
.findFirst(); // 找到第一个匹配项就停止
}
}这个实现存在两个主要局限性:
为了实现全树的深度遍历并收集所有匹配的部门,我们需要更强大的遍历机制,即递归或迭代方法。
立即学习“Java免费学习笔记(深入)”;
递归是处理树形结构最直观且优雅的方法之一。深度优先搜索(DFS)通过不断深入子节点,直到达到叶子节点,然后回溯,直到所有节点都被访问。
import java.util.ArrayList;
import java.util.List;
import java.util.Deque;
import java.util.ArrayDeque;
public class OrganizationSearcher {
private List<Department> rootDepartments; // 假设这是整个组织结构的根部门列表
public OrganizationSearcher(List<Department> rootDepartments) {
this.rootDepartments = rootDepartments;
}
/**
* 公开方法:通过递归方式查找所有指定类型的部门
* @param type 要查找的部门类型
* @return 匹配指定类型的所有部门列表
*/
public List<Department> findDepartmentByTypeRecursive(String type) {
ArrayList<Department> result = new ArrayList<>();
// 从根部门列表开始递归搜索
findDepartmentByTypeRecursiveImpl(type, rootDepartments, result);
return result;
}
/**
* 私有辅助方法:执行递归深度优先搜索
* @param type 要查找的部门类型
* @param departments 当前层级的部门列表
* @param result 收集匹配部门的结果列表
*/
private void findDepartmentByTypeRecursiveImpl(String type, List<Department> departments, List<Department> result) {
if (departments == null || departments.isEmpty()) {
return; // 基本情况:当前部门列表为空,停止递归
}
for (Department current : departments) {
// 1. 检查当前部门是否匹配
if (type.equals(current.getType())) {
result.add(current);
}
// 2. 如果当前部门是公司(即有子部门),则递归遍历其子部门
if (current instanceof Company) {
// 向下转型为Company,获取其子部门列表
findDepartmentByTypeRecursiveImpl(type, ((Company) current).getDepartments(), result);
}
}
}
}实现原理:
优点:
缺点:
为了避免递归可能导致的栈溢出问题,我们可以使用一个显式的栈(java.util.Deque)来模拟递归的调用过程,实现迭代的深度优先搜索。
import java.util.ArrayList;
import java.util.List;
import java.util.Deque;
import java.util.ArrayDeque;
public class OrganizationSearcher {
// ... (同上,包含rootDepartments和构造函数)
/**
* 公开方法:通过迭代方式(使用栈)查找所有指定类型的部门
* @param type 要查找的部门类型
* @return 匹配指定类型的所有部门列表
*/
public List<Department> findDepartmentByTypeIterative(String type) {
ArrayList<Department> result = new ArrayList<>();
// 使用Deque作为栈,ArrayDeque是推荐的实现
Deque<Department> stack = new ArrayDeque<>();
// 将所有根部门压入栈中,作为遍历的起点
if (rootDepartments != null) {
for (Department dept : rootDepartments) {
stack.push(dept); // 使用push将元素压入栈顶
}
}
// 当栈不为空时,持续进行遍历
while (!stack.isEmpty()) {
Department current = stack.pop(); // 弹出栈顶元素进行处理
// 1. 检查当前部门是否匹配
if (type.equals(current.getType())) {
result.add(current);
}
// 2. 如果当前部门是公司,则将其子部门压入栈中
// 注意:为了保持DFS的顺序(通常是先访问左子树再右子树),
// 如果希望子部门按特定顺序处理,压栈时需要注意顺序。
// 这里我们简单地将所有子部门压入,实际遍历顺序可能与递归略有不同,但最终会访问所有节点。
if (current instanceof Company) {
List<Department> children = ((Company) current).getDepartments();
if (children != null) {
// 逆序压入子部门,以确保在后续pop时,能够以预期的顺序(例如,与原列表顺序一致)处理
// 或者,如果顺序不重要,直接addAll即可
for (int i = children.size() - 1; i >= 0; i--) {
stack.push(children.get(i));
}
}
}
}
return result;
}
}实现原理:
优点:
缺点:
在Java中对树形结构进行深度搜索以查找特定元素时,递归和迭代是两种核心且有效的策略。
在实际开发中,应根据树的预期深度、代码的可读性偏好以及对性能和内存的特定要求,选择最适合的遍历方法。
以上就是Java树结构深度搜索:递归与迭代实现部门查找的详细内容,更多请关注php中文网其它相关文章!
每个人都需要一台速度更快、更稳定的 PC。随着时间的推移,垃圾文件、旧注册表数据和不必要的后台进程会占用资源并降低性能。幸运的是,许多工具可以让 Windows 保持平稳运行。
Copyright 2014-2025 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号