并查集--求解等价问题
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(); } } }