• 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 作为 对象成员 ,数据表成员 是伪子类!

       【测试】

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

      

        

  • 相关阅读:
    《Effective Java》读书笔记八(异常)
    《Effective Java》读书笔记七(通用程序设计)
    《Effective Java》读书笔记六(方法)
    《Effective Java》读书笔记五(枚举和注解)
    《Effective Java》读书笔记四(泛型)
    《Effective Java》读书笔记三(类和接口)
    《Effective Java》读书笔记二(通用方法)
    AngularJS的directive(指令)配置选项说明
    angularJS常见问题汇总
    angular指令中,require和transclude同时设置为true时的作用
  • 原文地址:https://www.cnblogs.com/onepersonwholive/p/12561733.html
Copyright © 2020-2023  润新知