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

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

  1. /**
  2. * 连通性算法
  3. */
  4. public interface UnionFind {
  5. /**
  6. * p点和q点之间添加一条通路
  7. *
  8. * @param p
  9. * @param q
  10. */
  11. void union(int p, int q);
  12.  
  13. /**
  14. * 获取p点的连通分量
  15. *
  16. * @param p
  17. * @return
  18. */
  19. int find(int p);
  20.  
  21. /**
  22. * 判断p点和q点是否存在一条通路
  23. *
  24. * @param p
  25. * @param q
  26. * @return
  27. */
  28. boolean connected(int p, int q);
  29.  
  30. /**
  31. * 连通分量的数量
  32. *
  33. * @return
  34. */
  35. int count();
  36. }

一、快速查询算法Quick-Find

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

  1. /**
  2. * 连通性算法:quick-find
  3. */
  4. public class QuickFind implements UnionFind {
  5. private int[] id; // 分量id
  6. private int count;
  7.  
  8. public QuickFind(int n) {
  9. count = n;
  10. id = new int[n];
  11. for (int i = 0; i < n; i++) {
  12. id[i] = i;
  13. }
  14. }
  15.  
  16. @Override
  17. public void union(int p, int q) {
  18. int pID = find(p);
  19. int qID = find(q);
  20.  
  21. if(pID == qID) {
  22. return;
  23. }
  24. for(int i = 0;i < id.length; i++) {
  25. if(id[i] == pID) {
  26. id[i] = qID;
  27. }
  28. }
  29. count--;
  30. }
  31.  
  32. @Override
  33. public int find(int p) {
  34. return id[p];
  35. }
  36.  
  37. @Override
  38. public boolean connected(int p, int q) {
  39. return find(p) == find(q);
  40. }
  41.  
  42. @Override
  43. public int count() {
  44. return count;
  45. }
  46. }

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

算法图示:

二、快速连接算法Quick-Union

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

  1. public class QuickUnion implements UnionFind {
  2. private int count;
  3. private int[] id;
  4.  
  5. public QuickUnion(int n) {
  6. count = n;
  7. id = new int[n];
  8. for(int i = 0; i < n; i++) {
  9. id[i] = i;
  10. }
  11. }
  12. @Override
  13. public void union(int p, int q) {
  14. int pRoot = find(p);
  15. int qRoot = find(q);
  16. if(pRoot == qRoot) {
  17. return;
  18. }
  19.  
  20. id[pRoot] = qRoot;
  21. count--;
  22. }
  23.  
  24. @Override
  25. public int find(int p) {
  26. while(p != id[p]) {
  27. p = id[p];
  28. }
  29. return p;
  30. }
  31.  
  32. @Override
  33. public boolean connected(int p, int q) {
  34. return false;
  35. }
  36.  
  37. @Override
  38. public int count() {
  39. return 0;
  40. }
  41. }

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

算法图示:

事实上,无论是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. swoole udp

    server.php <?php $server = new swoole_server('127.0.0.1', 9502, SWOOLE_PROCESS, SWOOLE_SOCK_UDP); ...

  2. nginx安装,反向代理配置

    1.centos 版本 下载最新稳定版 https://www.nginx.com/resources/wiki/start/topics/tutorials/install/# 2.执行语句: ./ ...

  3. yii2常用的migrate命令

    开发中经常会用到的方法小结: 1../yii migrate xxx_xx 在表中插入某字段 : public function up() {$this->addColumn('{{applic ...

  4. Object-C-NSFileHandle

    NSFileHandle 类中得到方法可以很方便的对文件数据进行读写.追加,以及偏移量的操作. NSFileHandle 基本步骤: 1.打开文件,获取一个NSFileHandle 对象 2.对打开N ...

  5. Intro to Python for Data Science Learning 4 - Methods

    Methods From:https://campus.datacamp.com/courses/intro-to-python-for-data-science/chapter-3-function ...

  6. Python: re.IGNORECASE 标志参数字符串忽略大小写的搜索替换

    为了在文本操作时忽略大小写,需要在使用re 模块的时候给这些操作提供re.IGNORECASE 标志参数.比如 >>> text = 'UPPER PYTHON, lower pyt ...

  7. 如何制作Windows镜像

    1.在https://msdn.itellyou.cn/网站中下载(使用迅雷)Windows2003R2 中文版ISO 2.使用qemu-img create命令创建一个空的 后缀为.img的文件 q ...

  8. Azkaban-开源任务调度程序(使用篇)

    上篇文章说到了安装,这次说说使用 登录 https://localhost:8443 注意是https,采用的是jetty ssl链接.输入账号密码azkaban/azkanban(如果你之前没有更改 ...

  9. Linux基础命令---mkisofs

    mkisofs mkisofs指令可以创建ISO9660/Joliet/HFS文件系统,现在使用指令genisoimage代替它.genisoImage是一个预掌握程序,用于生成iso 9660/jo ...

  10. C/C++之类型强制转化

    强制转化四种类型可能很多人都常常忽略就象我一样,但是有时还是比较有用的.不了解的建议看看,一些机制我也不是十分了解,只是将一些用法写出来让大家看看.                           ...