采用了启发式策略,按秩合并和路径压缩技术。
/// @file disjoint_set_forest.h
/// @brief 并查集
/// @copyright 玉涵,updated,2013/11/11
#include <iostream>
#include <vector>
using namespace std;
namespace algo
{
/// @brief 并查集的森林表示法
/// “压缩路径”+“按秩合并”优化时间
/// 线性时间复杂度,理论上是超线性的
class DisjointSetForest
{
public:
//集合中的一个元素
struct DisjointSetNode
{
int Item; //元素的值
int Rank; //元素的秩
DisjointSetNode *Parent; //元素的父结点
//构造函数,创建一个结点,对应MAKE-SET操作
DisjointSetNode(int const &item):Item(item),Rank(0)
{
Parent = this;
}
};
//创建一个集合 MAKE-SET
static DisjointSetNode* MakeSet(int const &item)
{
return new DisjointSetNode(item);
}
//查找所属集合的操作:FIND-SET 使用了路径压缩
static DisjointSetNode* FindSet(DisjointSetNode *a_set)
{
//路径压缩
if(a_set != a_set->Parent) //判断本身不是代表元素
{
a_set->Parent = FindSet(a_set->Parent);
}
return a_set->Parent;
}
//合并操作 UNION
static void Union(DisjointSetNode* x, DisjointSetNode* y)
{
_Link(FindSet(x), FindSet(y));
}
private:
static void _Link(DisjointSetNode* x, DisjointSetNode* y)
{
if(x->Rank > y->Rank)
{
y->Parent = x;
}
else
{
x->Parent = y;
}
//按秩合并
if(x->Rank == y->Rank)
{
//秩相同时将默认作为根结点的y秩+1
(y->Rank)++;
}
}
};
}