内容来自刘宇波老师算法与数据结构体系课
1、QuickFind
| public interface UF { |
| |
| int getSize(); |
| |
| |
| |
| |
| boolean isConnected(int p, int q); |
| |
| |
| |
| |
| void unionElements(int p, int q); |
| |
| } |
| |
| |
| |
| |
| |
| public class UnionFind1 implements UF { |
| |
| private final int[] id; |
| |
| public UnionFind1(int size) { |
| id = new int[size]; |
| for (int i = 0; i < size; i++) id[i] = i; |
| } |
| |
| @Override |
| public int getSize() { |
| return id.length; |
| } |
| |
| |
| |
| |
| private int find(int p) { |
| if (p < 0 || p >= id.length) throw new IllegalArgumentException("p is out of bound."); |
| return id[p]; |
| } |
| |
| @Override |
| public boolean isConnected(int p, int q) { |
| return find(p) == find(q); |
| } |
| |
| @Override |
| public void unionElements(int p, int q) { |
| int pID = find(p); |
| int qID = find(q); |
| |
| if (pID == qID) return; |
| |
| for (int i = 0; i < id.length; i++) { |
| if (id[i] == pID) id[i] = qID; |
| } |
| } |
| } |
2、QuickUnion
| |
| |
| |
| |
| |
| |
| public class UnionFind2 implements UF { |
| |
| private final int[] parent; |
| |
| public UnionFind2(int size) { |
| parent = new int[size]; |
| for (int i = 0; i < size; i++) parent[i] = i; |
| } |
| |
| @Override |
| public int getSize() { |
| return parent.length; |
| } |
| |
| |
| |
| |
| private int find(int p) { |
| if (p < 0 || p >= parent.length) throw new IllegalArgumentException("p is out of bound."); |
| while (p != parent[p]) p = parent[p]; |
| return p; |
| } |
| |
| @Override |
| public boolean isConnected(int p, int q) { |
| return find(p) == find(q); |
| } |
| |
| @Override |
| public void unionElements(int p, int q) { |
| int pRoot = find(p); |
| int qRoot = find(q); |
| |
| if (pRoot == qRoot) return; |
| |
| parent[pRoot] = qRoot; |
| } |
| } |
3、基于 size 进行优化
| |
| |
| |
| |
| |
| public class UnionFind3 implements UF { |
| |
| private final int[] parent; |
| private final int[] sz; |
| |
| public UnionFind3(int size) { |
| parent = new int[size]; |
| sz = new int[size]; |
| for (int i = 0; i < size; i++) { |
| parent[i] = i; |
| sz[i] = 1; |
| } |
| } |
| |
| @Override |
| public int getSize() { |
| return parent.length; |
| } |
| |
| |
| |
| |
| private int find(int p) { |
| if (p < 0 || p >= parent.length) throw new IllegalArgumentException("p is out of bound."); |
| while (p != parent[p]) p = parent[p]; |
| return p; |
| } |
| |
| @Override |
| public boolean isConnected(int p, int q) { |
| return find(p) == find(q); |
| } |
| |
| @Override |
| public void unionElements(int p, int q) { |
| int pRoot = find(p); |
| int qRoot = find(q); |
| |
| if (pRoot == qRoot) return; |
| |
| |
| if (sz[pRoot] < sz[qRoot]) { |
| parent[pRoot] = qRoot; |
| sz[qRoot] += sz[pRoot]; |
| } else { |
| parent[qRoot] = pRoot; |
| sz[pRoot] += sz[qRoot]; |
| } |
| } |
| } |
4、基于 rank 进行优化
| |
| |
| |
| |
| |
| public class UnionFind4 implements UF { |
| |
| private final int[] parent; |
| private final int[] rank; |
| |
| public UnionFind4(int size) { |
| parent = new int[size]; |
| rank = new int[size]; |
| for (int i = 0; i < size; i++) { |
| parent[i] = i; |
| rank[i] = 1; |
| } |
| } |
| |
| @Override |
| public int getSize() { |
| return parent.length; |
| } |
| |
| |
| |
| |
| private int find(int p) { |
| if (p < 0 || p >= parent.length) throw new IllegalArgumentException("p is out of bound."); |
| while (p != parent[p]) p = parent[p]; |
| return p; |
| } |
| |
| @Override |
| public boolean isConnected(int p, int q) { |
| return find(p) == find(q); |
| } |
| |
| @Override |
| public void unionElements(int p, int q) { |
| int pRoot = find(p); |
| int qRoot = find(q); |
| |
| if (pRoot == qRoot) return; |
| |
| |
| if (rank[pRoot] < rank[qRoot]) parent[pRoot] = qRoot; |
| else if (rank[qRoot] < rank[pRoot]) parent[qRoot] = pRoot; |
| else { |
| parent[pRoot] = qRoot; |
| rank[qRoot] += 1; |
| } |
| } |
| } |
5、路径压缩 1

| |
| |
| |
| |
| |
| |
| public class UnionFind5 implements UF { |
| |
| private final int[] parent; |
| private final int[] rank; |
| |
| public UnionFind5(int size) { |
| parent = new int[size]; |
| rank = new int[size]; |
| for (int i = 0; i < size; i++) { |
| parent[i] = i; |
| rank[i] = 1; |
| } |
| } |
| |
| @Override |
| public int getSize() { |
| return parent.length; |
| } |
| |
| |
| |
| |
| private int find(int p) { |
| if (p < 0 || p >= parent.length) throw new IllegalArgumentException("p is out of bound."); |
| while (p != parent[p]) { |
| parent[p] = parent[parent[p]]; |
| p = parent[p]; |
| } |
| return p; |
| } |
| |
| @Override |
| public boolean isConnected(int p, int q) { |
| return find(p) == find(q); |
| } |
| |
| @Override |
| public void unionElements(int p, int q) { |
| int pRoot = find(p); |
| int qRoot = find(q); |
| |
| if (pRoot == qRoot) return; |
| |
| |
| if (rank[pRoot] < rank[qRoot]) parent[pRoot] = qRoot; |
| else if (rank[qRoot] < rank[pRoot]) parent[qRoot] = pRoot; |
| else { |
| parent[pRoot] = qRoot; |
| rank[qRoot] += 1; |
| } |
| } |
| } |
5、路径压缩 2

| |
| |
| |
| |
| |
| |
| public class UnionFind6 implements UF { |
| |
| private final int[] parent; |
| private final int[] rank; |
| |
| public UnionFind6(int size) { |
| parent = new int[size]; |
| rank = new int[size]; |
| for (int i = 0; i < size; i++) { |
| parent[i] = i; |
| rank[i] = 1; |
| } |
| } |
| |
| @Override |
| public int getSize() { |
| return parent.length; |
| } |
| |
| |
| |
| |
| private int find(int p) { |
| if (p < 0 || p >= parent.length) throw new IllegalArgumentException("p is out of bound."); |
| |
| if (p == parent[p]) return p; |
| |
| parent[p] = find(parent[p]); |
| return parent[p]; |
| } |
| |
| @Override |
| public boolean isConnected(int p, int q) { |
| return find(p) == find(q); |
| } |
| |
| @Override |
| public void unionElements(int p, int q) { |
| int pRoot = find(p); |
| int qRoot = find(q); |
| |
| if (pRoot == qRoot) return; |
| |
| |
| if (rank[pRoot] < rank[qRoot]) parent[pRoot] = qRoot; |
| else if (rank[qRoot] < rank[pRoot]) parent[qRoot] = pRoot; |
| else { |
| parent[pRoot] = qRoot; |
| rank[qRoot] += 1; |
| } |
| } |
| } |
6、总结
| 并查集用于解决连接问题 |
| |
| 1、QuickFind、QuickUnion |
| 2、基于 size 的优化:让 "元素个数少的集合" 合并到 "元素个数多的集合" 上,使得合并后的新树,深度尽量不要增加 |
| 3、基于 rank 的优化:让 "层数低的集合" 合并到 "层数高的集合" 上,使得合并后的新树,深度尽量不要增加 |
| 4、路径压缩:压缩树的高度使其尽可能的矮 |
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步