并查集

来源:互联网 发布:好看便宜围巾 知乎 编辑:程序博客网 时间:2024/06/04 01:01

并查集:

           在一些有N个元素的集合应用问题中,我们通常是在开始时让每个元素构成一个单元素的集合,然后按一定顺序将属于同一组的元素所在的集合合并,期间要反复查找一个元素在哪个集合中。这一类问题近几年来反复出现在信息学的国际国内赛题中,其特点是看似并不复杂,但数据量极大,若用正常的数据结构来描述的话,往往在空间上过大,计算机无法承受;即使在空间上勉强通过,运行的时间复杂度也极高,根本就不可能在比赛规定的运行时间(1~3秒)内计算出试题需要的结果,只能用并查集来描述。

定义:

          并查集是一种树形的数据结构,用于处理一些不相交集合的合并及查询问题。集就是让每个元素构成一个单元素的集合,也就是按一定顺序将属于同一组的元素所在的集合合并。

图片展现过程:

                

              

代码实现:

#include <iostream>#include <assert.h>#include <Windows.h>using namespace std;class UnionFindSet{public:UnionFindSet(size_t size):_size(size){_a = new int[size];      //开辟空间for (size_t i = 0; i < size; ++i){_a[i] = -1;    //初始化为-1}}int FindRoot(int x)    //找根,小于0的为根{while (_a[x] >= 0){x = _a[x];}return x;}void Union(int x1, int x2)   //合并{int root1 = FindRoot(x1);int root2 = FindRoot(x2);_a[root1] = _a[root1] + _a[root2];_a[root2] = root1;}bool IsInOneSet(int x1, int x2)    //判断两个数据是否在一个集合里{return FindRoot(x1) == FindRoot(x2);}size_t SetSize()     //集合的个数{size_t count = 0;for (size_t i = 0; i < _size; ++i){if (_a[i] < 0){++count;}}return count;}protected:int* _a;    //数组size_t _size;    //个数};


#include "UnionFindSet.h"void TestUnionFindSet(){int arr[] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };size_t size = sizeof(arr) / sizeof(arr[0]);UnionFindSet qq(size);cout<< "找到的根为:"<< qq.FindRoot(10)<<endl;qq.Union(1, 2);qq.Union(1, 5);qq.Union(1, 9);qq.Union(2, 10);qq.Union(10, 7);qq.Union(7, 6);cout <<"是否在一个集合内:"<< qq.IsInOneSet(3,1) << endl;cout <<"该数组中并查集的个数:"<< qq.SetSize() << endl;cout << "找到的根为:" << qq.FindRoot(10) << endl;}int main(){TestUnionFindSet();system("pause");return 0;}