zoukankan      html  css  js  c++  java
  • union-find 算法

    union-find :用于解决触点之间的连通性问题,有一下三种算法。

    /**
     * QuickFind 快速查找法
     * 特点:能够以常数级的时间查找某一触点在哪个分量, 但是在最坏的情况下连接的花费是平凡级的。
     *
     * 成员变量:数组arr、分量数count(数组的索引表示各个触点、数组的值表示各个触电所在的分量)
     * 私有方法:
     * 公开方法:联合 union、查找分量 find、是否联通 connection
     * 要求:触电不能重复,以int来表示各触点。
     */
    public class QuickFind {
        private int[] arr;
        public int count;
    
        public QuickFind(int n) {
            arr = new int[n];
            for(int i=0;i<n;i++){
                arr[i]=i;
            }
            this.count = n;
        }
    
        public void union (int p,int q){
            if(connection(p,q))return;
            int numq = arr[q];
            int nump = arr[p];
            for(int i=0;i<arr.length;i++){
                if(arr[i] == numq){
                    arr[i] = nump;
                }
            }
            count--;
        }
    
        public int find(int p){
            if(p>=0&&p<arr.length) return arr[p];
            return -1;
        }
    
        public boolean connection(int p, int q){
            if(find(p)==find(q)) return true;
            return false;
        }
    }
    /**
     * @ClassName WeightQuickUnionDemo
     * @Author wangyudi
     * @Date 2019/7/20 14:06
     * @Version 1.0
     * @Description
     * 各分量带有权重的快速联合方法
     * 使用两个数组,一个数组用于存放节点的联通信息,另一个数组存放节点所在分量的权重信息
     * 成员: 节点数组;权重数组;分量数量
     * 方法:查找结点所在的分量find;联合两个分量union;判断两个节点是否联通 connection;返回分量数 size
     */
    public class WeightQuickUnionDemo {
        private int[] info; //存放联通信息
        private int [] weight; //存放权重信息
        private int count;
    
        public WeightQuickUnionDemo(int count) {
            this.info = new int[count];
            this.weight = new int[count];
            for(int i=0;i<count;i++){
                info[i]=i;
                weight[i]=1;
            }
            this.count = count;
        }
    
        /**
         * info 数组中存放节点之间的联通信息,如果数组中存放的值和数组的索引一致表示该节点是所在分量的根节点
         * @param num
         * @return
         */
        public int find(int num){
            while (num != info[num]) num = info[num];
            return num;
        }
    
        /**
         * 联合num1 和 num2 两个分量
         * 注意点:先判断两个节点是否在同一个分量中
         * 将权重比较小的分量连接到分量比较大的分量
         * 修改分量数
         * 修改权重
         * @param num1
         * @param num2
         */
        public void union(int num1,int num2){
            int rootNum1 = find(num1);
            int rootNum2 = find(num2);
            if(rootNum1==rootNum2) return;
            if(weight[rootNum1]>weight[rootNum2]){ //num1 所在分量的权重比较大
                weight[rootNum1] += weight[rootNum2];
                info[rootNum2]=rootNum1;
                count--;
            }
            else {
                weight[rootNum2] += weight[rootNum1];
                info[rootNum1]=rootNum2;
                count--;
            }
        }
    
        public boolean connection(int num1,int num2){
            return find(num1)==find(num2)?true:false;
        }
    
        public int size(){
            return count;
        }
    }
    /**
     * 测试案例
     */
    public class TestCase {
        public static void main(String[] args) {
            QuickFind quickFind = new QuickFind(10);
            quickFind.union(4,3);
            quickFind.union(8,3);
            quickFind.union(5,6);
            quickFind.union(4,9);
            quickFind.union(2,1);
            quickFind.union(5,0);
            quickFind.union(7,2);
            quickFind.union(6,1);
            System.out.println(quickFind.count);
            System.out.println(quickFind.find(9));
            System.out.println(quickFind.connection(4,2));
            System.out.println("=======================");
            QuickUnion quickUnion = new QuickUnion(10);
            quickUnion.union(4,3);
            quickUnion.union(8,3);
            quickUnion.union(5,6);
            quickUnion.union(4,9);
            quickUnion.union(2,1);
            quickUnion.union(5,0);
            quickUnion.union(7,2);
            quickUnion.union(6,1);
            System.out.println(quickUnion.count);
            System.out.println(quickUnion.find(9));
            System.out.println(quickUnion.connection(2,4));
            System.out.println("=========================");
            WeightedQuickUnion weightedQuickUnion = new WeightedQuickUnion(10);
            weightedQuickUnion.union(4,3);
            weightedQuickUnion.union(8,3);
            weightedQuickUnion.union(5,6);
            weightedQuickUnion.union(4,9);
            weightedQuickUnion.union(2,1);
            weightedQuickUnion.union(5,0);
            weightedQuickUnion.union(7,2);
            weightedQuickUnion.union(6,1);
            System.out.println(weightedQuickUnion.count);
            System.out.println(weightedQuickUnion.find(9));
            System.out.println(weightedQuickUnion.connection(2,4));
        }
    }
    
    
    //结果
    2
    8
    false
    =======================
    2
    8
    false
    =========================
    2
    3
    false
  • 相关阅读:
    毛笔算法 毛笔签名效果
    手写输入控件
    全栈工程师成长路线
    配置msdtc
    流行的广告轮播(图片轮播)JS代码!!
    水晶报表放上去网站会爆:bobj错误的
    查询所有存储过程
    VB.NET and C# Comparison
    SQL查询案例:多行转换为一行
    SQL Server行列转换[转]
  • 原文地址:https://www.cnblogs.com/youzoulalala/p/11090894.html
Copyright © 2011-2022 走看看