并查集是一种奇怪的树结构。在并查集中,不是父亲指向孩子,而是孩子指向父亲。这样的一种奇怪结构,却能出奇快的解决集合相关的合并和查询问题。在这一章,我们将连续优化我们的并查集,释放出并查集的最大能量!一般有两个操作 union(p,q)并 find(p)查
sConnected( p , q ),传入 p 和 q 两个元素,判断两个元素是否相连接
并查集的基本数据表示
对于如上需求,最简单的数据表示方式就是数组,其中:数组的索引
用来表示元素
如果有 0-9,共 10 个元素,这些元素之间连接关系的表示方法如下:
(1)
0-4 对应的值都是 0,而 5-9 对应的值都是 1。表示 0-4 这 5 个元素之间是互相连接的,而 5-9 这 5 个元素之间是互相连接的
(2)
0、2、4、6、8 对应的值都是 0,而 1、3、5、7、9 对应的值都是 1。表示 5 个偶数和 5 个奇数是分别互相连接的
不妨给这个数组起一个名字,叫做 id,即 所有连接在一起的元素,它们都具有相同的id
Quick Find
Union()时间复杂度O(n),find() 时间复杂度O(1);
数据表示方式:数组 id [ ]
c++代码实现
#include <bits/stdc++.h>
using namespace std;
/*并查集Union Find QuickFind
*/
class UnionFind{
private:
int *id; //一个id的数组
int count; //一共多少元素
public:
UnionFind( int n ){
//初始化传入数组有多少元素
count = n;
id = new int[n]; //开辟n个元素大小的数组空间
//开始时每个元素都是自己独立的组
for(int i = 0;i < n;i++ )
id[i] = i;
}
~UnionFind()
{
delete [] id;
}
//实现find() 时间复杂度行为O(1)
int find( int p )
{
assert( p>=0&&p<count );
return id[p];
}
//实现Union() 时间复杂度为O(n)
void Union( int p,int q )
{
int pID = find(p);
int qID = find(q);
if( pID == qID )
return;
for( int i = 0;i < count;i++ )
if( id[i] == qID )
id[i] == pID;
}
//传入p q两个元素,判断两点是否是相连接的
bool isConnected( int p,int q ){
return find(p) == find(q);
}
};
int main()
{
return 0;
}
Quick-Union
初始化时将数组下的每个元素看做一个独立的节点
用数组parent的下标和下标下的数据将每个节点连接起来。
eg: 判断parent[5] 的根节点
parent[5] = 0; //说明数组数据为5的上一个节点为数组数据为0。
向上依次递推
... ......
数据表示方式:数组parent [ ]
c++代码实现
#include <bits/stdc++.h>
using namespace std;
/*并查集Union Find
*/
class UnionFind{
private:
int *parent; //一个parent的数组
int count; //一共多少元素
public:
UnionFind( int n ){
//初始化传入数组有多少元素
count = n;
parent = new int[n]; //开辟n个元素大小的数组空间
//开始时每个元素都是自己独立的组
for(int i = 0;i < n;i++ )
parent[i] = i;
}
~UnionFind()
{
delete [] parent;
}
//实现find() 时间复杂度行为O(1)
int find( int p )
{
assert( p>=0&&p<count );
while( p!=parent[p] )
p = parent[p]; //向上查找根节点
return p;
}
//实现Union() 时间复杂度为O(n)
void Union( int p,int q )
{
int pRoot = find(p); //找到p元素对应的根
int qRoot = find(q); //找到q元素对应的根
if(pRoot == qRoot)
return; //如果p元素对应的根与q元素对应的根相等,那么说明两者已经相连接了
parent[pRoot] = qRoot; //把p对应的parent设置为q的根那么两者就相连了
}
//传入p q两个元素,判断两点是否是相连接的
bool isConnected( int p,int q ){
return find(p) == find(q);
}
};
int main()
{
return 0;
}