您的位置:首页 > 理论基础 > 数据结构算法

并查集--求解等价问题

2017-05-20 22:20 176 查看

什么是并查集

有多个集合,集合内有多个元素

并查集算法用来查找一个元素所属的集合,合并两个元素各自所属的集合。称为并查集

算法举例

亲戚关系的等价问题,犯罪团伙的头目。

给出很多人的亲戚相互间关系,查找任意两人是否为亲戚。

多个犯罪分子各自在自己的团伙中,找到犯罪团伙的数量。

算法思路

使用树的数据结构来实现并查集算法。

关键点:

1. 初始化集合,刚开始每个元素为一个集合,该元素就代表了该集合;如果有多个元素,根元素代表一个集合。根节点的parent指针指向自己。(元素间虽然有父子关系但是不意味者有从属关系,只是起到联系集合元素的作用)

2. 查找一个元素所属的集合。找该元素所在集合的根节点。

3. 合并集合。为了使合并后的树的高度更小,需要将高度较小的树作为高度较大的树的子树。若两树的高度相等需要将高度+1;

算法实现

java实现

package aha_algorithm;

import java.io.BufferedReader;
import java.io.InputStreamReader;

public class MergeSearchSet {

public static class MSSNode{
int id;//元素编号
int rank;//树的高度称为秩
int parent;//父节点下标
}

static int elementNum;
static int relationNum;

static MSSNode[] MSSTree;

/**
* @param args
*/
public static void main(String[] args) {
initSet();
judgeRelation();
}

public static void initSet(){
BufferedReader input = new BufferedReader(new InputStreamReader(System.in));

try {
String[] inLine = input.readLine().split(" ");

elementNum= Integer.valueOf(inLine[0]);
relationNum = Integer.valueOf(inLine[1]);

MSSTree = new MSSNode[elementNum];
//初始化关系树
for (int i = 0; i < elementNum; i++) {
MSSNode tempNode = new MSSNode();
tempNode.id=i;
tempNode.rank=0;
tempNode.parent=i;

MSSTree[i]= tempNode;
}

//获取关系并 合并
for (int i = 0; i < relationNum; i++) {
String[] relation = input.readLine().split(" ");

int idLeft= Integer.valueOf(relation[0]);
int idRight = Integer.valueOf(relation[1]);
mergeSet(idLeft, idRight);
}

}catch(Exception e){
e.printStackTrace();
}
}

static int findSet(int id){
if(id == MSSTree[id].parent){
return id;
}
return findSet(MSSTree[id].parent);
}

static void mergeSet(int idLeft,int idRight){
int parentLeft = findSet(idLeft);
int parentRight = findSet(idRight);

if(MSSTree[parentLeft].rank < MSSTree[parentRight].rank){
MSSTree[parentLeft].parent = parentRight;
}else{
MSSTree[parentRight].parent = parentLeft;
if(MSSTree[parentLeft].rank == MSSTree[parentRight].rank){
MSSTree[parentLeft].rank++;
}
}
}

static void judgeRelation(){
BufferedReader input = new BufferedReader(new InputStreamReader(System.in));

try {
String[] inLine = input.readLine().split(" ");
int id1, id2;

id1 = Integer.valueOf(inLine[0]);
id2 = Integer.valueOf(inLine[1]);
if(findSet(id1)==findSet(id2)){
System.out.println(id1+"和"+id2+"是亲戚");
}else{
System.out.println(id1+"和"+id2+"不是亲戚");
}
}catch(Exception e){
e.printStackTrace();
}
}
}


时间复杂度

主要时间在查找元素所在的集合即找根节点。所有时间复杂度为logN。N为元素个数
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  数据结构 算法 合并