赞
踩
每个集合用一棵“有根树”表示 定义数组 set[1…n] set[i] = i, 则i表示本集合,且是集合对应树的根 set[i] = j,j<>i, 则 j 是 i 的父节点.
- int findSet(int x)
- {
- if (x == set[x])
- return x;
- else
- return findSet(set[x]);
- }
- void unionSet(int x, int y)
- {
- int fx = findSet(x);
- int fy = findSet(y);
- set[fy] = fx;
- }
i | 1 | 2 | 3 | 4 | 5 |
set[i] | 1 | 2 | 3 | 4 | 5 |
i | 1 | 2 | 3 | 4 | 5 |
set[i] | 1 | 1 | 3 | 4 | 5 |
i | 1 | 2 | 3 | 4 | 5 |
set[i] | 1 | 1 | 3 | 5 | 5 |
i | 1 | 2 | 3 | 4 | 5 |
set[i] | 1 | 1 | 3 | 5 | 1 |
启发式合并 方法:将深度小的树合并到深度大的树 实现:假设两棵树的深度分别为h1和h2, 则合并后的树的高度h是: max(h1,h2), if h1<>h2. h1+1, if h1=h2. 效果:任意顺序的合并操作以后,包含k个节点的树的最大高度不超过lgk
- void unionSet(int x, int y)
- {
- fx = findset(x);
- fy = findset(y);
- if(rank[fx] > rank[fy])
- {
- set[fy] = fx;
- }
- else
- {
- set[fx] = fy;
- if(rank[fx] == rank[fy])
- rank[fy]++;
- }
- }
路径压缩(Path Compression) 思想:每次查找的时候,把经过路径上的点的父亲都设为根 步骤: 第一步,找到根结点 第二步,修改查找路径上的所有节点,将它们都指向根结点 可以证明m次操作的总时间复杂度为k*O(m),k是一个接近1的常数,即几乎是线性的。 使用路径压缩的并查集算法不需要再使用启发式合并。
- int findSet(int x)
- {
- if (x == set[x])
- return x;
- else
- return set[x] = findSet(set[x]);
- }
期望复杂度 O(m log n),最坏复杂度 O(nm)。
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。