小言_互联网的博客

并查集

261人阅读  评论(0)

并查集(union-find算法):一种树型结构,用于处理一些不交集的合并及查询问题

最重要的两个方法:
find:用于查找元素属于哪一个子集,可以用来判断两个元素是否属于同一个集合

union:将两个子集合并成为一个集合

趣味理解:其实并查集的运用就是一个小弟确认帮派、找老大的操作。例如在古惑仔中,洪兴和东星都有自己的龙头大哥,而且洪兴和东星是死对头,双方遇见了就会干架,但是洪兴和东星都规定帮内成员不能打架,而且帮派等级森严,小弟们只知道自己的大哥是谁,而不知道龙头大哥是谁,这时双方都不能确认对方是不是死对头,这时候他们就打电话确认对方的身份。

例如

场景一:A和B在烧烤摊因为一串热狗准备干架了,但是苦于规矩,他们要先打电话确认对方的身份。

这时A打电话给自己的老大山鸡,山鸡打电话给老大陈浩南,陈浩南又打电话给蒋先生;B也给自己的大哥大飞打电话,大飞又打电话给蒋先生,然后A报了自己的身份说我是蒋先生的人,此时B也说我也是蒋先生的人。A和B看了看对方都笑了,原来是兄弟,所以他们就和好了,两个人一起吃了这串热狗。

场景二:B又在烧烤摊和C发生矛盾了,这次是因为一串韭菜,他们这时就打电话确认对方的身份

B打电话给大哥大飞,大飞打电话给蒋先生,同时C也给自己的老大乌鸦打电话,乌鸦又给大哥骆驼打电话。B说我是蒋先生的人,C说我是骆驼的人,双方一听,马上叫上自己的兄弟,TMD是敌人,往死里整,然后B就赢到了这串韭菜,东星输给了洪兴。古惑仔的世界胜者为王,败者为寇,此时东星已经被洪兴打败了,所以东星被洪兴吞并了。

东星被吞并后

具体实现步骤

init:定义一个集合(古惑仔的世界),有N个元素(N个古惑仔),每个元素都是一个集合(每个人都是自己的龙头大哥),所以此时有N个集合(N个帮派)


  
  1. public static int[] teenage= null; //元素集合
  2. public static int count = 0; //集合数量
  3. //初始化
  4. public static void init(int N){
  5. count = N;
  6. heroes = new int[N];
  7. for ( int i = 0; i < N; i++){
  8. heroes[i] = i;
  9. }
  10. }

find:元素确定自己所在集合(小弟找龙头大哥的操作)


  
  1. public static int find(int id){
  2. // 如果自己不是龙头大哥就继续寻找
  3. while (id != teenage[id]){
  4. id = teenage[id];
  5. }
  6. return id;
  7. }

union:将两个子集合并成为一个集合(两个帮派合并)


  
  1. public static void union(int p, int q){
  2. int pID = find(p); // 确定自己所在集合(找龙头大哥)
  3. int qID = find(q); // 确定自己所在集合(找龙头大哥)
  4. if (pID == qID){
  5. // 同一个帮派,不能干架,吃烧烤去
  6. return;
  7. }
  8. // 不是同一个帮派,召集人干架,但是由于q要比p要厉害一点,所以呢,q就吞并了p
  9. // p的龙头大哥就成了q的龙头大哥的小弟
  10. teenage[pID] = qID;
  11. // 集合减少一个(p的帮派消失了)
  12. count--;
  13. }

完整代码


  
  1. package com.company.unionFind;
  2. import java.util.Scanner;
  3. public class UF_quickUnion {
  4. public static int[] teenage = null;
  5. public static int count = 0;
  6. public static void init(int N){
  7. count = N;
  8. teenage = new int[N];
  9. for ( int i = 0; i < N; i++){
  10. teenage[i] = i;
  11. }
  12. }
  13. public static int find(int id){
  14. while (id != teenage[id]){
  15. id = teenage[id];
  16. }
  17. return id;
  18. }
  19. public static void union(int p, int q){
  20. int pID = find(p);
  21. int qID = find(q);
  22. if (pID == qID){
  23. return;
  24. }
  25. teenage[pID] = qID;
  26. count--;
  27. }
  28. public static void main(String[] args){
  29. init( 10);
  30. Scanner scanner = new Scanner(System.in);
  31. int p, q;
  32. while((p = scanner.nextInt()) != - 1 && (q = scanner.nextInt()) != - 1){
  33. union(p,q);
  34. }
  35. System.out.println( "剩下 " + count + " 个集合");
  36. }
  37. }

测试数据


  
  1. 4 3
  2. 3 8
  3. 6 5
  4. 9 4
  5. 2 1
  6. 8 9
  7. 5 0
  8. 7 2
  9. 6 1
  10. 1 0
  11. 6 7

输出

剩下 2 个集合

 


转载:https://blog.csdn.net/weixin_41856902/article/details/104930763
查看评论
* 以上用户言论只代表其个人观点,不代表本网站的观点或立场