PHP并查集需基于父节点数组实现,结合路径压缩与按秩合并优化:初始化各元素自为根;find递归压缩路径;union比较秩决定挂载方向;还可封装为Trait复用。

如果您需要在PHP中实现并查集(Union-Find)数据结构以支持动态连通性判断与集合合并操作,则需围绕父节点数组和路径压缩/按秩合并两大优化机制构建。以下是实现此结构的具体方法:
一、基于数组与路径压缩的并查集实现
该方法使用一维整型数组存储每个元素的父节点索引,初始化时每个元素自成一类;查找时递归向上并同步将沿途节点直接指向根节点,显著降低后续查询时间复杂度。
1、定义一个类 UnionFind,声明私有属性 $parent 和 $size(可选,用于按秩合并)。
2、在构造函数中接收元素总数 n,初始化 $parent 为长度为 n 的数组,令 $parent[i] = i。
立即学习“PHP免费学习笔记(深入)”;
3、实现 find 方法:若 $parent[x] ≠ x,则递归调用 find($parent[x]) 并将结果赋给 $parent[x],最后返回 $parent[x]。
4、实现 union 方法:先分别调用 find 获取两元素根节点,若根不同,则将其中一个根的父节点设为另一个根。
二、带按秩合并优化的并查集实现
该方法在 union 操作中引入秩(rank)数组记录各树近似高度,优先将低秩树根挂到高秩树根下,避免树退化为链表,进一步保障操作效率。
1、在类中新增私有属性 $rank,初始化为全0数组,长度与 $parent 相同。
2、修改 union 方法:获取两元素根节点 rootX 和 rootY 后,比较 $rank[rootX] 与 $rank[rootY]。
3、若 $rank[rootX]
4、当 $rank[rootX] == $rank[rootY] 时,任选其一作为新根,并将该根对应 $rank 值加1。
三、支持元素值非连续整数的哈希映射实现
当输入元素为字符串、对象或稀疏整数时,无法直接用数组下标索引,需借助关联数组建立元素到内部整数ID的双向映射,再在其上构建标准并查集。
1、在类中维护两个私有属性:$idMap(元素→ID)、$reverseMap(ID→元素),以及标准 $parent 数组。
2、实现 add 方法:若元素未注册,则分配新ID(如当前最大ID+1),存入 $idMap 和 $reverseMap。
3、find 和 union 方法均先通过 $idMap 将传入元素转为ID,再调用底层整数版逻辑。
4、提供 findElement 方法:对给定元素调用 find 得到根ID,再通过 $reverseMap 返回对应原始元素值。
四、使用SplFixedArray提升性能的实现
对于大规模固定规模数据,SplFixedArray 可替代普通数组以减少内存开销与哈希查找延迟,尤其适用于已知最大元素数量且不频繁扩容的场景。
1、在构造函数中根据预估规模 n 初始化 $parent = new SplFixedArray(n)。
2、确保所有对 $parent 的访问均使用整数索引,且不超出范围,否则抛出 RuntimeException。
3、初始化循环中使用 $parent->offsetSet(i, i) 替代 $parent[i] = i。
4、find 方法内调用 $parent->offsetGet(x) 获取父节点,union 中使用 offsetSet 更新父关系。
五、封装为可复用Trait的实现方式
将并查集核心逻辑抽象为 trait,便于在多个业务类中混入,避免重复编码,同时保持接口一致性与类型安全。
1、定义 trait UnionFindTrait,包含 protected 属性 $parent、$rank、$count。
2、提供 abstract protected function getElementCount(): int;由宿主类实现以告知元素总数。
3、实现 public function find(int $x): int 和 public function union(int $x, int $y): void 方法。
4、在宿主类中 use UnionFindTrait,并在 __construct 中调用 $this->init() 初始化数组,其中调用 getElementCount() 确定尺寸。



















