并查集: 通过数组来实现的一种将有关系的节点都联系起来的一种搜索结构。
代码实现:
#include<iostream>
#include<vector>
using namespace std;
class UnionFindSet
{
public:
UnionFindSet(size_t size)
:_n(size)
{
_set.resize(size,-1);
}
void Union(int root1, int root2) //结合两个节点
{
int index = root1;
if (_set[root1] >= 0)
index = FindRoot(root1);
_set[index] += _set[root2];
_set[root2] =index;
}
size_t FindRoot(int index) //找父节点的位置
{
if (_set[index] < 0) //负数表示当前位置为父节点
{
return index;
}
int num = _set[index];
int set = 0;
while (num>=0)
{
set = num;
num = _set[num];
}
return set;
}
int Size() //朋友圈的个数
{
int count= 0;
for (size_t i = 0; i < _n; i++)
{
if (_set[i] < 0)
count++;
}
return count;
}
private:
vector<int> _set;
size_t _n; //给定范围数据的个数
};
void test()
{
UnionFindSet u1(10);
u1.Union(0,6);
u1.Union(6,7);
u1.Union(7,8);
u1.Union(1, 4);
u1.Union(1, 9);
u1.Union(2, 3);
u1.Union(2, 5);
u1.Union(1, 2);
u1.Size();
}
使用场景:
假如已知有n个人和m对好友关系(存于数字r)。如果两个人是直接或间接的好友(好友的好友的好友…),则认为他们属于同一个朋友圈,请写程序求出这n个人里一共有多少个朋友圈。
假如:n = 5 , m = 3 , r = {{1 , 2} , {2 , 3} , {4 , 5}},表示有5个人,1和2是好友,2和3是好友,4和5是好友,则1、2、3属于一个朋友圈,4、5属于另一个朋友圈,结果为2个朋友圈。 最后请分析所写代码的时间、空间复杂度。评分会参考代码的正确性和效率。
代码实现:
调用上面的代码即可
void test2()
{
UnionFindSet u2(6);
u2.Union(1,2);
u2.Union(2, 3);
u2.Union(4,5);
//0号位置没有使用,所以在算朋友圈的个数时要减去一个
cout << "朋友圈的个数:" << u2.Size() - 1 << endl;
}