【第22期】观点:IT 行业加班,到底有没有价值?

动态连通性问题

原创 2016年05月30日 13:37:00

动态连通性问题算法实现及优化

首先定义算法的API

方法 作用
UF(int N) 初始化触点及其他数据
int find(int p) 返回p所在连通分量的标识符
int union(int p,int q) 在p和q之间添加一条线
int count () 返回连通分量的数量
boolean connected(int p,int q) 如果p和q之间有一条线就返回true

1.好了,API已经定义好了,下面可以实现这个API,下面是第一个版本。实现思想是利用判断id[q]和id[p]是否相等来判断它们是否在同一个连通分量中。它的缺点是一般无法处理大规模问题,因为每次调用它都需要扫描一次数组,对于最终值得到少量连通分量的问题运行时间是平方级别的。

public class UnionFind {
    private int count;//记录连通分支数
    private int[] id;
    public UnionFind(int N){
        count = N;
        id = new int[N];
        for(int i = 0;i<N;i++)//完成将id初始化0~N-1
            id[i] = i;
    }
    public int find(int p){
        return id[p];
    }
    public int getCount(){
        return count;
    }
    public boolean connected(int p,int q){
        return id[p] == id[q];
    }
    public void union(int p, int q){//缺点:一般无法处理大规模问题,因为每次调用它都需要扫描一次数组,对于最终值得到少量连通分量的问题运行时间是平方级别的
        int pID = id[p];
        int qID = id[q];
        if(pID == qID) //思路:利用判断id[q]和id[p]是否相等来判断它们是否在同一个连通分量中
            return;//如果相等就什么也不做,因为它们本来就在一个连通分支里面
        for(int i = 0;i<id.length;i++){
            if(id[i] == pID)
                id[i] = qID;//将p所在的连通支路全部改为q,合并两个连通分支
        }
        count--;//合并之后因为连通分支数少一,所以减一
    }
}

2.上面的那个算法不适用与大数据处理,原因是对于最终得到的连通分量问题的运行时间是平方级别的。下面的这个算法它优化了union()方法,并修改了find()方法以配合union()方法的使用。它的设计思想是定义与之前不同的数据结构,每个触点所对应的id[]元素都是同一个分量中的另一个触点的名称(也有可能是它自己)——我们将这种联系称为链接。每个连通分量都有一个根触点。根触点的特点是id[i] = i。这种数据结构使得union()在最坏情况下得到的结果是平方级别的,一般情况下是线性对数级别的。而find()方法的运行时间取决于数的高度。

public class QuickUnion {
    private int count;//记录连通分支数
    private int[] id;
    public QuickUnion(int N){
        count = N;
        id = new int[N];
        for(int i = 0;i<N;i++)//完成将id初始化0~N-1
            id[i] = i;
    }
    public int find(int p){
        while(p != id[p])
            p = id[p];
        return p;//返回连通标号
    }
    public int getCount(){
        return count;
    }
    public boolean connected(int p,int q){
        return find(p) == find(q);
    }
    public void union(int p, int q){//最坏情况下得到的连通分量运行时间是平方级别的
        int pRoot = find(p);
        int qRoot = find(q);
        if(pRoot == qRoot)
            return;
        id[pRoot] = qRoot;
        count--;
    }
}

3.下面是第三种方法实现,它进一步优化了第二种实现,使得在最坏情况下union()也保持线性对数级别的运行时间。设计思想是在union()中不是随意将一棵树链接到另一棵树中,而是通过添加一个数组来记录每颗数的大小,将较小的一颗链接到较大的一颗树上。我们将它称为加权quick-union算法。

public class WeightedQuickUnion {
    private int[] id;//父链接数组,由触点作为缩引
    private int[] sz;//存储各个触点具有的数据个数
    private int count;
    public WeightedQuickUnion(int N){
        count = N;
        id = new int[N];
        sz = new int[N];
        for(int i = 0;i<N;i++){
            id[i] = i;
            sz[i] =1;
        }
    }
    public int getCount(){
        return count;
    }
    public boolean connected(int p,int q){
        return find(p) == find(q);
    }
    private int find(int p){
        while(p != id[p])
            p = id[p];
        return p;
    }
    public void union(int p,int q){
        int i = find(p);
        int j = find(q);
        if(i == j)
            return;
        if(sz[i] < sz[j]){//将较小的连通分量链接到较大的连通分量中
            id[i] = j;
            sz[j] += sz[i];
        }
        else{
            id[j] = i;
            sz[i] += sz[j];
        }
        count --;
    }
}

总结:由上面的算法优化可以知道,算法优化不是一步到位的,它中间需要一个过程

版权声明:本文为博主原创文章,未经博主允许不得转载。 举报

相关文章推荐

动态连通性、并查集(union-find)算法介绍

本文主要介绍解决动态连通性一类问题的一种算法,使用到了一种叫做并查集的数据结构,称为Union-Find。更多的信息可以参考Algorithms 一书的Section 1.5,实际上本文也就是基于它的...

6:动态连通性 (并查集)

1: 动态连通性    可以检测所给的点中 是否有环的:     概念: <ul style="margin-bottom: 0px; padding-bottom: 10px; color: #555555; font-family...

程序员升职加薪指南!还缺一个“证”!

CSDN出品,立即查看!

基于连通性状态压缩的动态规划问题

基于连通性状态压缩的动态规划问题

[双连通+割点+桥]无向图连通性问题专题

最近一直搞专辑,所以没写啥解题报告,今天终于搞完了一个,小结一下下 题目来源,LightOJ,在Problem Category里的Graph Theory里的<a class="us

动态连通性问题

动态连通性问题算法实现及优化首先定义算法的API 方法 作用 UF(int N) 初始化触点及其他数据 int find(int p) 返回p所在连通分量的标识符 int u...

用telnet的方式检验远程服务器的连通性,在tomcat中遇到问题

用了apache.commons.net.telnet包来实现telnet远程服务器某个端口是否开通从而来判断远程服务器是否能连通。 结果出现以下问题: 在[b]公司内网[/b]中并且是在tomcat中 ,即便远程服务器(远程服务器在公司外网)停止, 但是telnet.isConnected(...
收藏助手
不良信息举报
您举报文章:深度学习:神经网络中的前向传播和反向传播算法推导
举报原因:
原因补充:

(最多只允许输入30个字)