上一章我大概说明了什么是图论以及无向图的基础概念,本章我们要研究一种更普遍的算法——连通性算法。它属于图论的分支,也是一种抽象算法。在深入算法之前,我们先提出一个具体的问题:假设在空间中存在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. cheng gong de daima

    /** * Copyright (c) 2012-2016 ebizwindow, Inc. All rights reserved. * * Permission is hereby granted ...

  2. Ignite初探

    Guava是一个很方便的本地缓存工具,但是在多节点处理的过程中,本地缓存无法满足数据一致性的问题.分布式缓存Ignite很好的解决了数据一致性,可靠性,事务性等方面的问题. Ignite支持分区方式和 ...

  3. 2018-2019-2 20165209 《网络对抗技术》 Kali安装

    2018-2019-2 20165209 <网络对抗技术> Kali安装 目录内容 下载 安装 网络 共享 软件源 下载kali kali下载官网地址 我下载的版本(如下图所示) 安装 打 ...

  4. LLVM/Clang编译相关研究

    https://blog.csdn.net/guojin08/article/details/54310858 https://juejin.im/entry/5c64da44518825620b45 ...

  5. linux常见命令ps的应用

    ps(Process Status)命令是linux中最常见的命令之一,它用来列出当前系统运行中的进程的状态信息.当然了,它只显示命令执行时的进程状态,如果想要动态列出状态信息,可以选择使用top命令 ...

  6. Linux中Postfix虚拟用户及虚拟域(六)

    Postfix基于虚拟用户虚拟域的邮件架构 上图是一个几乎完整的邮件系统架构图,这里基于Mysql数据库进行用户认证,不管是Postfix.Dovecot.webmail都需要去Mysql数据库中进行 ...

  7. SNMP学习笔记之Linux下安装和配置SNMP

    注意:本篇安装用户是root,非root用户启动的时候会报缺少文件错误. 一.安装SNMP 1.1.下载Net-SNMP的源代码 选择一个SNMP版本,比如5.7.1,下载地址如下:http://so ...

  8. SNMP学习笔记之SNMPWALK 安装与使用详解

    0x00 简介 snmpwalk是SNMP的一个工具,它使用SNMP的GETNEXT请求查询指定OID(SNMP协议中的对象标识)入口的所有OID树信息,并显示给用户.通过snmpwalk也可以查看支 ...

  9. 20165211 2017-2018-2 《Java程序设计》第7周学习总结

    20165211 2017-2018-2 <Java程序设计>第7周学习总结 教材学习内容总结 本周,我学习了书本上第十一章的内容,以下是我整理的主要知识. 第十一章 JDBC和MySQL ...

  10. keil5配置stm32库函数开发

    在将模板文件添加到工程中后, 1.点击魔术棒,选择C/C++,添加头文件的路径: 2.C/C++里面的define内填入:STM32F10X_MD,USE_STDPERIPH_DRIVER: 3.Ou ...