并查集:
将N个不同的元素分成一组不相交的集合。
开始时,每个元素就是一个集合,然后按规律将两个集合进行合并。
原理:
两个数元素中选择一个元素作为根,让另一个元素对应下表的内容加到第一个元素对应下标的内容中,并把另一个元素下标对应内容变为第一个的元素。
(1)申请一块数组用以标记元素之间的关系
初始化
给定一个关系,用上图进行标记,如果两个元素之间不是同一个的根就把第二个元素当作下标取刚申请的数组中的内容加到第一个元素对应下标的内容中,最后负数 的个数就是大关系的个数。
单关系图:
多关系图:
面试题,可以使用并查集,代码在下面:
#include<iostream>
using namespace std;
class SearchSet
{
public:
/*构造的时候申请一个数组,给他初始化为-1*/
SearchSet(size_t size)
:_size(size),
_set(new int[size])
{
for (size_t i = 0; i < size; i++)
{
_set[i] = -1;
}
}
int FindRoot(int child)
{
int parent = child;
while (_set[parent]>=0)
{
parent = _set[parent];
}
return parent;
}
void Union(int x, int y)
{
int m=FindRoot(x);
int n=FindRoot(y);
if (m == n)
return;
else
{
_set[m] += _set[n];
_set[n] = m;
}
}
void Print()
{
for (size_t i = 0; i < _size; i++)
{
cout << _set[i] << " ";
}
}
/*找出关系的总数*/
int FriendCount()
{
int count = 0;
for (size_t i = 0; i < _size; i++)
{
if (_set[i] < -1)//考虑没有关系0内有作用,就把0号下标对应的-1去掉
{
count++;
}
}
return count;
}
private:
int *_set;
size_t _size;
};
void testSearchSet()
{
SearchSet s(10);
s.Union(0, 6);
s.Union(0, 7);
s.Union(0, 8);
s.Union(1, 4);
s.Union(1, 9);
s.Union(2, 3);
s.Union(2, 5);
s.Union(0, 1);
s.Print();
}
/*小米面试题:*/
void Frient()
{
const int M = 3;
const int N = 2;
int arr[M][N] = { { 1, 2 }, { 2, 3 }, { 4, 5 } };
SearchSet s(6);
for (int i = 0; i < M; i++)
{
s.Union(arr[i][0], arr[i][1]);
}
size_t count = s.FriendCount();
cout << count<<endl;
}
int main()
{
//testSearchSet();
Frient();
system("pause");
return 0;
}