上一章我大概说明了什么是图论以及无向图的基础概念,本章我们要研究一种更普遍的算法——连通性算法。它属于图论的分支,也是一种抽象算法。在深入算法之前,我们先提出一个具体的问题:假设在空间中存在N个点,我们可以通过线段连接任意两点,相互连接的点属于同一组连通分量,我们如何计算点p和点q之间是否连通。算法的核心是:如何表示连通性以及如何检查连通性。

下面提供算法的抽象接口:

/**
* 连通性算法
*/
public interface UnionFind {
/**
* p点和q点之间添加一条通路
*
* @param p
* @param q
*/
void union(int p, int q); /**
* 获取p点的连通分量
*
* @param p
* @return
*/
int find(int p); /**
* 判断p点和q点是否存在一条通路
*
* @param p
* @param q
* @return
*/
boolean connected(int p, int q); /**
* 连通分量的数量
*
* @return
*/
int count();
}

一、快速查询算法Quick-Find

我们将空间中的点这一概念抽象成int[](整形数组),i代表不同的点int[i]代表不同的连通分量。一种比较容易理解的想法是,从属于同一组连通分量的任一点p和q必定int[p]等于int[q]。因此当我们需要查询点p和q是否连通的时候只需要判断int[p] == int[q]是否成立即可。

/**
* 连通性算法:quick-find
*/
public class QuickFind implements UnionFind {
private int[] id; // 分量id
private int count; public QuickFind(int n) {
count = n;
id = new int[n];
for (int i = 0; i < n; i++) {
id[i] = i;
}
} @Override
public void union(int p, int q) {
int pID = find(p);
int qID = find(q); if(pID == qID) {
return;
}
for(int i = 0;i < id.length; i++) {
if(id[i] == pID) {
id[i] = qID;
}
}
count--;
} @Override
public int find(int p) {
return id[p];
} @Override
public boolean connected(int p, int q) {
return find(p) == find(q);
} @Override
public int count() {
return count;
}
}

find()操作的速度显然是很快的,因为它只需要访问id[]数组一次。但是对于每一对数组union()都需要扫描整个id[]数组。因此quick-find算法一般无法处理大型数组。

算法图示:

二、快速连接算法Quick-Union

我们要讨论的下一个算法的重点是提高union()方法的速度,为此可能会稍微牺牲一下find()的效率,但是通常情况下这样做是值得的。Quick-Union算法考虑把属于同一组连通分量的点连接成一棵树,i代表点,int[i]代表i的父节点,根节点p等于int[p]。

public class QuickUnion implements UnionFind {
private int count;
private int[] id; public QuickUnion(int n) {
count = n;
id = new int[n];
for(int i = 0; i < n; i++) {
id[i] = i;
}
}
@Override
public void union(int p, int q) {
int pRoot = find(p);
int qRoot = find(q);
if(pRoot == qRoot) {
return;
} id[pRoot] = qRoot;
count--;
} @Override
public int find(int p) {
while(p != id[p]) {
p = id[p];
}
return p;
} @Override
public boolean connected(int p, int q) {
return false;
} @Override
public int count() {
return 0;
}
}

快速连接算法的每一次连接会分别遍历两次连通分量,在连通分量中包含元素数量相对总数而言比较小的情况下可以提供非常不错的速度。

算法图示:

事实上,无论是Quick-Find算法还是Quick-Union算法,他们在图论的基础上基本是起到相互补充的作用。更重要的一点是,我们通过对他们的学习可以认识到,十全十美的算法很难实现,更多的时候算法针对某一个问题的痛点才是有效的。

小橙书阅读指南(十三)——连通性算法(union-find)的更多相关文章

  1. 对象模型图(OMD)阅读指南

    樱木 原文 对象模型图(OMD)阅读指南(转载) 补充几个名词概念: UML:Unified Modeling Language 统一建模语言,是用来对软件密集系统进行可视化建模的一种语言.UML为面 ...

  2. QQ小橙团队排表机器人使用方法

    版权声明 别瞎JB玩坏了...一个群一个群导入很累的 联系QQ: 986859110 目录 网页版使用说明 登录和权限操作 团队和模板选择操作 模板使用案例 团队面板操作 老板管理 人员管理 QQ群机 ...

  3. 微信小程序把玩(三十三)Record API

    原文:微信小程序把玩(三十三)Record API 其实这个API也挺奇葩的,录音结束后success不走,complete不走,fail也不走, 不知道是不是因为电脑测试的原因,只能等公测或者等他们 ...

  4. 微信小程序把玩(二十三)modal组件

    原文:微信小程序把玩(二十三)modal组件 modal弹出框常用在提示一些信息比如:退出应用,清楚缓存,修改资料提交时一些提示等等. 常用属性: wxml <!--监听button点击事件-- ...

  5. 清橙 A1206 小Z的袜子(莫队算法)

    A1206. 小Z的袜子 时间限制:1.0s   内存限制:512.0MB   总提交次数:1357   AC次数:406   平均分:46.75   将本题分享到:        查看未格式化的试题 ...

  6. 转:苹果Xcode帮助文档阅读指南

    一直想写这么一个东西,长期以来我发现很多初学者的问题在于不掌握学习的方法,所以,Xcode那么好的SDK文档摆在那里,对他们也起不到什么太大的作用.从论坛.微博等等地方看到的初学者提出的问题,也暴露出 ...

  7. 数据结构看书笔记(二)--算法(Algorithm)简介

    算法:是解决问题求解步骤的描述,在计算机中表现为指令的有限序列,并且每条指令表示一个或多个操作. 算法的特性:算法具有五个特性:输入.输出.有穷性.确定性.可行性 输入输出:算法具有零个或多个输入:至 ...

  8. 两百条微信小程序跳坑指南(不定时更新)

    微信小程序联盟出品 跳坑textarea<二百二十三>不显示文本及textarea相关问题集合跳坑<二百一十三> background-image无法获取本地资源图片....跳 ...

  9. 算法竞赛进阶指南 0x00 基本算法

    放在原来这个地方不太方便,影响阅读体验.为了读者能更好的刷题,另起一篇随笔. 0x00 基本算法 0x01 位运算 [题目][64位整数乘法] 知识点:快速幂思想的灵活运用 [题目][最短Hamilt ...

随机推荐

  1. python 爬取文章

    这里我们利用强大的python爬虫来爬取一篇文章.仅仅做一个示范,更高级的用法还要大家自己实践. 好了,这里就不啰嗦了,找到一篇文章的url地址:http://www.duanwenxue.com/a ...

  2. Python: TypeError: 'dict' object is not callable

    问题:  TypeError: 'dict' object is not callable 原因:  dict()是python的一个内建函数,如果将dict自定义为一个python字典,在之后想调用 ...

  3. linux常用命令:sudo 命令

    sudo命令用来以其他身份来执行命令,预设的身份为root. 1.命令格式: sudo  [参数]  [命令] 2.命令功能: 功能:  sudo可以针对单个命令授予临时权限.用户也可以通过su切换到 ...

  4. input/radio/select等标签的值获取和赋值

    input/radio/select等标签的值获取和赋值,这几个是使用率最高的几个标签,获取值和赋值以及初始化自动填充数据和选择: 页面html: <div class=" " ...

  5. python 用正则表达式把”0102030405”分成5组('0', '1'), ('0', '2'), ('0', '3'), ('0', '4'), ('0', '5')

    把”0102030405”分成5组('0', '1'), ('0', '2'), ('0', '3'), ('0', '4'), ('0', '5') re.findall(r"(\d)(\ ...

  6. 在线js调试工具JSbin、jsFiddle

    在线js调试工具JSbin.jsFiddle JS Bin - Collaborative JavaScript Debugginghttp://jsbin.com/?html,output这个在线j ...

  7. C/C++之全局、static对象/变量的初始化问题

    关于全局.static对象/变量的初始化问题 1. 全局变量.static变量的初始化时机:main()函数执行之前(或者说main中第一个用户语句执行之前). 2. 初始化顺序. 1)全局对象.外部 ...

  8. 编译安装 http

    1. 安装 apr http服务依赖 apr和apr-util ,安装 http 前需先安装这两个程序 apr 简介:http://www.cnblogs.com/Alight/p/3997777.h ...

  9. django 项目中使用多数据库 multiple databases

    假如在一个django项目中使用到了不只一个数据库, 其实这在大一点的工程中很常见,比如主从库 那么会涉及到如下一些东西 1, 定义 在settings中的DATABASE中定义会使用到的数据,比如除 ...

  10. 20145106 java 实验四

    这次的实验是Android开发实验基础.Android开发是一个很大的工程,但是这次只是一个小小的入门. 首先将SDK文件复制到-根目录下,之后将Android Studio复制到电脑里. 并指明SD ...