并查集

来源:互联网 发布:php继承一个普通类 编辑:程序博客网 时间:2024/06/10 21:36

在计算机科学中,并查集是一种树型的数据结构,其保持着用于处理一些不相交集合(Disjoint Sets)的合并及查询问题。有一个联合-查找算法union-find algorithm)定义了两个操作用于此数据结构:

  • Find:确定元素属于哪一个子集。它可以被用来确定两个元素是否属于同一子集。
  • Union:将两个子集合并成同一个集合
(维基百科)

带路径压缩的 Find:
所谓路径压缩,是一种在执行“查找”时扁平化树结构的方法。关键在于在路径上的每个节点都可以直接连接到根上;他们都有同样的表示方法。为了达到这样的效果,Find递归地经过树,改变每一个节点的引用到根。得到的树将更加扁平,为以后直接或者间接引用节点的操作加速。
递归:
int Find(int x){    return parent[x] == x ? x : parent[x] = Find(parent[x]);}
迭代:
int Find(int x){    if(x != parent[x])    {        parent[x] = parent[parent[x]];        x = parent[x];    }    return x;}

按秩合并 Union:
合并两棵树的时候,极有可能形成的树一头轻一头重,极不平衡,减低了Find查找的效率,因此提出秩的概念。
这里的秩有两种定义:
1. 算导上的定义:秩表示结点高度的一个上界。具体操作是 让具有较小秩的根指向具有较大秩的根。
2. 另一种定义:秩表示该结点所在树的大小,即拥有的结点个数。以size小的树作为子树和size大的树进行合并。
-----1.
void Union(int p, int q){    int x = Find(p);    int y = Find(q);        if(x == y) return;    if(rank[x] > rank[y])        parent[y] = x;    else    {        parent[x] = y;        if(rank[x] == rank[y])            rank[y]++;    }}
-----2.
void Union(int p, int q){    int i = Find(p);    int j = Find(q);    if(i == j) return;    if(rank[i] < rank[j]){        parent[i] = j;        rank[j] += rank[i];    }    else{        parent[j] = i;        rank[i] += rank[j];    }}

判断两个元素是否属于同一集合:
bool isSame(int x, int y){    return Find(x) == Find(y);}




0 0
原创粉丝点击