并查集(disjoint set)¶
- 并查集是一种数据结构,它支持:
- 查找(Find):确定某个元素属于哪个子集
- 合并(Union):合并两个子集
等价关系¶
- 自反性(reflexive):\(\forall a, a \sim a\)
- 对称性(symmetric):\(\forall a, b, a \sim b \Rightarrow b \sim a\)
- 传递性(transitive):\(\forall a, b, c, a \sim b, b \sim c \Rightarrow a \sim c\)
储存¶
- 用树来表示集合,树的根节点是集合的代表元
-
用数组来表示树:
根节点的typedef struct { ElementType Data;// the value of the element int Parent;// the index of the parent node }SetType;
Parent
为-1 -
也可简化表示:
S[root] = -1;
S[i] = j 表示i的父节点是j
操作¶
- 查找元素X所在集合: 从下往上找到根节点
若采取简化表达:
- 合并两个集合:
- 找到两个元素所在集合的根节点;
- 若根节点不同,则将其中一个根节点的
Parent
设置为另一个根节点的数组下标
若采取简化表示:
可以想见,这样的合并操作多次进行会使树的高度增加,从而影响查找操作的效率。为了降低树的高度,可以采用:
- 按秩合并:
- 按大小:将节点数较少的树合并到节点数较多的树上
- 将S[root]修改为-|T|,其中T是树的节点数
- 按大小合并所得树的高度最大为\(\lfloor \log_2 N \rfloor + 1\)
- 按高度:将高度较小的树合并到高度较大的树上
- 按大小:将节点数较少的树合并到节点数较多的树上
- 路径压缩:在查找根节点的过程中,将沿途的所有节点的
Parent
都设置为根节点好处是多次查找时除了第一次外,后续查找的时间复杂度为\(O(1)\)SetName Find( SetType S, ElementType X ) { if( S[X] < 0 ) return X; // X is the root else return S[X] = Find( S, S[X] ); // first, find the root; then, link all the nodes in this path to the root }
以及Find是尾递归,可以被优化为迭代。
最后更新:
2024年10月2日 14:45:20
创建日期: 2024年4月9日 15:03:21
创建日期: 2024年4月9日 15:03:21