1. 并查集的基础操作与复杂度中路径压缩+按秩合并为什么能把单次操作摊还到 O(α(n)),只压缩不按秩合并在最坏情况下的退化?
并查集的基础操作与复杂度,说明路径压缩+按秩合并为何把单次操作摊还到 O(α(n)),以及只压缩不按秩合并在最坏情况下的退化?
- find/union 基础操作
- 路径压缩 + 按秩合并
- 只压缩不按秩合并的退化
并查集基础:find(x) 找根(路径压缩),union(a,b) 把两个集合合并(按秩合并)。路径压缩 + 按秩合并使单次操作摊还 O(α(n))(α 为反阿克曼函数,实际 ≤4)。路径压缩把 find 路径上的节点直接指向根,降低下次 find 深度;按秩合并把较小的树挂到较大的树下,控制树高。两者结合保证树高极低,摊还近乎 O(1)。只压缩不按秩合并:不按秩合并时,树可能退化(如一直把大树挂到小树下,或链式合并),树高可能高达 O(n),某些 find 最坏 O(n);虽然路径压缩会缓解,但最坏情况下单次 find 仍可能 O(n)(如构造特殊合并顺序使路径压缩难以降低树高)。故两者缺一不可。
O(α(n)) 依赖"路径压缩 + 按秩合并"协同。按秩合并用"秩"控制树高,路径压缩用"扁平化"降低访问深度。只压缩不按秩合并因树高可能失控,最坏退化到 O(n)。掌握"why both"是复杂度证明的关键。
int find(int x) { if (parent[x] != x) parent[x] = find(parent[x]); return parent[x]; }
void union(int a, int b) {
int ra = find(a), rb = find(b);
if (ra == rb) return;
if (rank[ra] < rank[rb]) parent[ra] = rb;
else if (rank[ra] > rank[rb]) parent[rb] = ra;
else { parent[rb] = ra; rank[ra]++; }
}