一:并查集数据结构
在计算机科学中,并查集是一种树型的数据结构,其保持着用于处理一些不相交集合(Disjoint Sets)的合并及查询问题。有一个联合-查找算法(union-find algorithm)定义了两个操作用于此数据结构:
- Find:确定元素属于哪一个子集。它可以被用来确定两个元素是否属于同一子集。
- Union:将两个子集合并成同一个集合。
因为它支持这两种操作,一个不相交集也常被称为联合-查找数据结构(union-find data structure)或合并-查找集合(merge-find set)。其他的重要方法,MakeSet,用于建立单元素集合。有了这些方法,许多经典的划分问题可以被解决。
二:并查集结构基本操作的实现
#define MAX 100
int father[MAX]; //用于记录对应节点的父节点
int rank[MAX]; //用于两个集合合并时进行比较
int make_set(int nums)
{
for (int i=0;i<nums;i++)
{
father[i]=i; //默认父节点为自己的编号
}
return 0;
}
//查找某个元素所在集合的代表
//在一棵树中,可以认为是查找该节点所在树的根节点
int find_set(int x)
{
if (x!=father[x])
{
father[x]=find_set(father[x]);//路径压缩,更精确的应该加上rank[]的修改
}
return father[x];
}
//如果两个元素在同一个集合就返回,否则依据rank进行集合的合并
void union_set(int x,int y)
{
x=find_set(x);
y=find_set(y);
if (x==y)
return ;
if (rank[x]>rank[y])
{
father[y]=x;
}
else
{
if (rank[x]==rank[y])
{
rank[y]++;
}
father[x]=y;
}
}
三:算法问题的描述
If there are different pairs of characters, each pair of the characters means the two matching characters are the same. Print out all the identical characters.
For example:
if you have pairs:
A-B
C-D
E-F
G-H
A-D
F-G
you should print out:
{A, B, C, D} are the same characters.
{E, F, G, H} are the same characters.
四:利用并查集的解决方案
针对问题,建立叫Pair的结构,用于记录每一个pair中的两个字符,以及一个ID用于区别不同的Pair。把每一个pair当做并查集中的基本元素来进行前面进行的基本操作,为方便使用,建立一个map<Pair,int>,用于记录每个Pair与父节点之间的对应关系。代码实现如下:
#include <iostream>
#include <map>
using namespace std;
#define MAX 100
typedef struct
{
char first;
char second;
int ID; //唯一区分每个Pair
}Pair;
map<Pair,int> father_map;
int rank[MAX];
int make_set(Pair& temp_pair)
{
father_map[temp_pair]=temp_pair.ID;
rank[temp_pair.ID]=0;
}
int find_set(Pair& l_pair)
{
int father;
map<Pair,int>::const_iterator iter=father_map.find(l_pair);
if (iter!=father_map.end())
{
father=iter->second;
}
if (father!=l_pair->ID)
{
father=find_set(iter->first);
}
father_map[l_pair]=father;
return father;
}
void union_set(Pair lpair,Pair rpair)
{
int lfather=find_set(lpair);
int rfather=find_set(rpair);
if (lfather==rfather)
{
return ;
}
if (rank[lfather]>rank[rfather])
{
father_map[rpair]=lfather;
}
else
{
if (rank[lfather]==rank[rfather])
{
rank[rfather]++;
}
father_map[lpair]=rfather;
}
}
五:参考资料
http://zh.wikipedia.org/wiki/%E5%B9%B6%E6%9F%A5%E9%9B%86
http://www.cnblogs.com/cherish_yimi/archive/2009/10/11/1580839.html