Java 编写 并查集 算法—— [针对自己最新确认的代码编写规范]

日期:2020.03.24

博客期:168

星期二

 

  【博客前言】

    众所周不知啊,我在上大一的时候,进入了我们学校的ACM-算法竞赛协会,当时学习的成员还不多,但是学习氛围很好,我上的第一堂课就是关于并查集的使用,我就用当时才学完的 C语言实现了。我对于这个算法可以说是记忆犹新吧!这个例子我学了C++以后也实现过,那么今天就轮到我使用 Java 在设计模式和最近新确定好的Java代码规范的基础下再来实现这个“并查集”算法!

  【代码功能】

    并查集的适用场景:在分散的许多结点中,人为的添加一些点到点的线,使其构成多条树(每条树对应一个分组),可以判定两个结点是否有线路可以流通、可以人为地将两个分组连接起来。

       【实装代码】

    com.bcj 包:

      数字并查集类:

  1 package com.bcj;
  2 
  3 import java.util.ArrayList;
  4 import java.util.List;
  5 
  6 // Readme:
  7 //
  8 //    English Name: UnionCheckingSet Class
  9 //    Chinese Name: 数字并查集类
 10 //
 11 // Writen by NS-Studio in 2020-03-24 17:41
 12 //
 13 public class UnionCheckingSet{
 14     //----------------------<成员属性>----------------------//
 15     //
 16     //---[基本类型]
 17     
 18     //最大长度
 19     private int max_len;
 20     
 21     //父节点集合
 22     private List <Integer> self_list;
 23     
 24     //父节点连线权值集合
 25     private List <Integer> par_list;
 26     
 27     //----------------------<成员方法>----------------------//
 28     //
 29     //---[配置方法]
 30     
 31     //初始化
 32     private void init() {
 33         this.reset();
 34     }
 35     
 36     //重新初始化
 37     public void reset() {
 38         // 初始化 长度
 39         this.self_list = new ArrayList <Integer> ();
 40         this.par_list = new ArrayList <Integer> ();
 41         
 42         // 给 数据 加上 1 对 1 的索引
 43         for(int i=0;i<this.max_len;++i)
 44         {
 45             this.self_list.add(i);
 46             this.par_list.add(0);
 47         }
 48     }
 49     
 50     //
 51     //---[实用方法]
 52     
 53     //查找根节点
 54     public int find_root_code(int index) {
 55         // 我们 获取 它的父节点
 56         int tmp = this.self_list.get(index);
 57         
 58         // 如果 父节点 是 它本身,说明 它就是 根节点
 59         if(index == tmp)
 60             return index;
 61         // 否则 它的根节点 就是 它的 父节点的 根节点
 62         else
 63             return this.find_root_code(tmp);
 64     }
 65     
 66     //两个结点是否相互连接
 67     public boolean is_linked(int index_1,int index_2) {
 68         // 如果 两个结点 所对应的 根节点 相同,那么 我们认为 它们是在连在一起的
 69         return this.find_root_code(index_1) == this.find_root_code(index_2);
 70     }
 71     
 72     //两个结点相互连接
 73     public void unite_code(int index_1,int index_2) {
 74         // 将 结点 由 它们各自的 根节点 代替
 75         index_1 = this.find_root_code(index_1);
 76         index_2 = this.find_root_code(index_2);
 77         
 78         // 如果 这两个结点 不在同一组内, 则将 根节点 相连
 79         if(index_1!=index_2)
 80         {
 81             // 准备 权值信息 储存器
 82             int par_1,par_2;
 83             
 84             // 储存器 赋值
 85             par_1 = this.par_list.get(index_1);
 86             par_2 = this.par_list.get(index_2);
 87             
 88             // 储存器值 高的 一方 作为 根节点
 89             if(par_1 < par_2)
 90             {
 91                 this.self_list.set(index_1,index_2);
 92             }
 93             // 如果 储存器值 相等 ,则 需要 轻微 调高 作为 根结点的 储存器值(不等不强制)
 94             else
 95             {
 96                 this.self_list.set(index_2,index_1);
 97                 this.par_list.set(index_1, par_1 + 1);
 98             }
 99         }
100     }
101     
102     //
103     //---[构造方法]
104     
105     //无参构造 : 参数 max_len 默认值为 1010
106     public UnionCheckingSet() {
107         super();
108         // 无参的 设置默认值
109         this.max_len = 1010;
110         this.init();
111     }
112     
113     //单参构造
114     public UnionCheckingSet(int max_len) {
115         super();
116         // 单参的 设置 max_len 值
117         this.max_len = max_len;
118         this.init();
119     }
120     
121     //
122     //---[测试方法]
123     
124     // -----
125     // 主方法
126     //
127     //        测试用例 :
128     //            分成三组——(1,3,4,6),(2,7),(5)
129     //            测试 1,3 和 2,5 分别 是否处在同一组
130     public static void main(String[] args) {
131         // 实例化 一个 并查集 对象
132         UnionCheckingSet ucs = new UnionCheckingSet();
133         
134         // 定义 一个 变量 :用于 存储 boolean 数据
135         boolean is = false;
136         
137         // 连接对象 分组
138         //         ---[A组]
139         ucs.unite_code(1,3);
140         ucs.unite_code(3,4);
141         ucs.unite_code(1,6);
142         //         ---[B组]
143         ucs.unite_code(2,7);
144         
145         // 测试 1,3 是否在同一组
146         //         ---[改数值]
147         is = ucs.is_linked(1,3);
148         //         ---[数据查看]
149         System.out.println(is);
150         
151         // 测试 2,5 是否在同一组
152         //         ---[改数值]
153         is = ucs.is_linked(2,5);
154         //         ---[数据查看]
155         System.out.println(is);
156     }
157 }
UnionCheckingSet.java

      并查集类:

  1 package com.bcj;
  2 
  3 import java.util.ArrayList;
  4 import java.util.List;
  5 
  6 // Readme:
  7 //
  8 //    English Name: MapCheckingSet Class
  9 //    Chinese Name: 并查集类
 10 //
 11 // Writen by NS-Studio in 2020-03-24 18:35
 12 //
 13 public class MapCheckingSet <T>{
 14     //----------------------<成员属性>----------------------//
 15     //
 16     //---[基本类型]
 17     
 18     //最大长度
 19     private int max_len;
 20     
 21     //数据列表
 22     private List <T> map_data;
 23     
 24     //并查集
 25     private UnionCheckingSet ucs;
 26     
 27     //----------------------<成员方法>----------------------//
 28     //
 29     //---[配置方法]
 30     
 31     //初始化
 32     private void init() {
 33         this.reset();
 34     }
 35     
 36     //重新初始化
 37     public void reset() {
 38         // 初始化 长度
 39         this.ucs = new UnionCheckingSet(this.max_len);
 40         
 41         // 初始化 数据表
 42         this.map_data = new ArrayList<T>();
 43     }
 44     
 45     //
 46     //---[实用方法]
 47     
 48     //添加结点
 49     public void add_code(T code_been_added) {
 50         // 如果 表中 没有,就 加进去
 51         if(!this.map_data.contains(code_been_added))
 52             this.map_data.add(code_been_added);
 53     }
 54     
 55     //查找结点的 index
 56     private int index_of_list(T code_been_selected) {
 57         // 位置 信息 索引
 58         return this.map_data.indexOf(code_been_selected);
 59     }
 60     
 61     //两个结点是否相互连接
 62     public boolean is_linked(T code_1,T code_2) {
 63         // this.index_of_list( index ) 是 list 中的索引地址 
 64         int index_1 = this.index_of_list(code_1);
 65         int index_2 = this.index_of_list(code_2);
 66         
 67         // 根据 实际的值 调用 数值型 并查集
 68         return this.ucs.is_linked(index_1, index_2);
 69     }
 70     
 71     //两个结点相互连接
 72     public void unite_code(T code_1,T code_2) {
 73         // this.index_of_list( index ) 是 list 中的索引地址 
 74         int index_1 = this.index_of_list(code_1);
 75         int index_2 = this.index_of_list(code_2);
 76         
 77         // 根据 实际的值 调用 数值型 并查集
 78         this.ucs.unite_code(index_1, index_2);
 79     }
 80     
 81     //
 82     //---[构造方法]
 83     
 84     //无参构造 : 参数 max_len 默认值为 1010
 85     public MapCheckingSet() {
 86         super();
 87         // 无参的 设置默认值
 88         this.max_len = 1010;
 89         this.init();
 90     }
 91     
 92     //单参构造
 93     public MapCheckingSet(int max_len) {
 94         super();
 95         // 单参的 设置 max_len 值
 96         this.max_len = max_len;
 97         this.init();
 98     }
 99     
100     //
101     //---[测试方法]
102     
103     // -----
104     // 主方法
105     //
106     //        测试用例 :
107     //            分成三组——(“李法”,“刘汉”,“王旺教”),(“孟兴”,“陶保”),(“田冒”,“赵埔彤”)
108     //            测试 “李法”,“刘汉” 和 “孟兴”,“田冒” 分别 是否处在同一组
109     public static void main(String[] args) {
110         // 实例化 一个 并查集 对象
111         MapCheckingSet <String> mcs = new MapCheckingSet<String>();
112         
113         // 定义 一个 变量 :用于 存储 boolean 数据
114         boolean is = false;
115         
116         //加入数据
117         mcs.add_code("李法");
118         mcs.add_code("刘汉");
119         mcs.add_code("王旺教");
120         mcs.add_code("孟兴");
121         mcs.add_code("陶保");
122         mcs.add_code("田冒");
123         mcs.add_code("赵埔彤");
124         
125         // 连接对象 分组
126         //         ---[A组]
127         mcs.unite_code("李法","刘汉");
128         mcs.unite_code("刘汉","王旺教");
129         //         ---[B组]
130         mcs.unite_code("孟兴","陶保");
131         //         ---[C组]
132         mcs.unite_code("田冒","赵埔彤");
133         
134         // 测试 “李法”,“刘汉” 是否在同一组
135         //         ---[改数值]
136         is = mcs.is_linked("李法","刘汉");
137         //         ---[数据查看]
138         System.out.println(is);
139         
140         // 测试 “孟兴”,“田冒” 是否在同一组
141         //         ---[改数值]
142         is = mcs.is_linked("孟兴","田冒");
143         //         ---[数据查看]
144         System.out.println(is);
145     }
146 }
MapCheckingSet.java

  【项目结构图】

  【类图】

     目前就两个类,实际上没什么看点

  【使用到的设计模式】

     1、模板方法模式:并查集的算法部分是模板方法(可以套用)

     2、适配器模式:这次还是隐式的对象适配器模式,把 UnionChckingSet 作为 对象成员 ,数据表成员 是伪子类!

   【测试】

    由于代码中测试信息较为详细,博主在这里不过多摄入。

  

    

posted @ 2020-03-24 20:43  初等变换不改变矩阵的秩  阅读(223)  评论(0编辑  收藏  举报