详细解析参照算法(第4版)1.5章——案例研究:union—find算法

1.union-find法的API

public class UF  
UF(int N) 以整数标识(0—N-1)初始化N个标识
void union(int p,int q) 在触点p和q之间添加一条连接
void find(int p) p所在连通分量的标识符(0—N-1)
void connected(int p,int q) 判断触点p和q是否连通,即p和q是否在同一连通分量
int count() 连通分量的数目

2.union-find的实现

   1: public abstract class UF {
   2:     protected int count;
   3:     protected int[] id;
   4:  
   5:     public UF(int N) {
   6:         count = N;
  27:             if (find(i) == pID)
   7:         id = new int[N];
   8:         for (int i = 0; i < N; i++)
   9:             id[i] = i;
  10:     }
  11:     
  12:     public abstract int find(int p);
  13:     
  14:     public abstract void union(int p,int q);
  15:     
  16:     public boolean connected(int p,int q){
  17:         return find(p) == find(q);
  18:     }
  19:     
  20:     public int count(){
  21:         return count;
  22:     }
  23: }

2.1.quick-find算法

   1: public class QuickFindUF extends UF {
   2:  
   3:     public QuickFindUF(int N) {
   4:         super(N);
   5:     }
   6:  
   7:     @Override
   8:     public int find(int p) {
   9:         // TODO Auto-generated method stub
  10:         // 触点p为索引,id[p]即是p所在的连通分量的标识符
  11:         return id[p];
  12:     }
  13:  
  14:     /**
  15:      * 如果p和q在同一个连通分量,则p和q连通 否则,要将p和q连通(两个连通分量合并),即将p的连通分量所有触点的连通分量改成q的连通分量
  16:      */
  17:     @Override
  18:     public void union(int p, int q) {
  19:         // TODO Auto-generated method stub
  20:         int pID = find(p);
  21:         int qID = find(q);
  22:  
  23:         if (pID == qID)
  24:             return;
  25:  
  26:         for (int i = 0; i < id.length; i++)
  27:             if (find(i) == pID)
  28:                 id[i] = qID;
  29:         count--;
  30:     }
  31:     
  32:     
  33:  
  34: }

算法分析

1.union(p,q)会访问数组次数N+3~2N+1

分析:(1)两次find()操作,访问2次数组

(2)扫描整个数组id[],判断p和q是否在同一个连通f分量if(find(i)==pID),访问N次数组

(3)①只有p,其余触点均不和p在同一连通分量 id[p] =qID,访问1次数组

②除了q本身,其余均和p在同一连通分量 id[i] = qID(i≠q),访问 N-1次数组,故总的访问次数①2+N+1 = N+3        ②2+N+N-1 = 2N+1

2.在最好的情况下(union(p,q)访问数组N+3次),N个整数要进行N-1次合并union(p,q)操作,访问数组(N+3)(N-1)~N^2。

quick-union算法是平方级别的。

测试结果

   1: public static void main(String[] args) {
   2:     DirectInput.directInput(args);
   3:     int N = StdIn.readInt();
   4:     UF uf = new QuickFindUF(N);
   5:     while(!StdIn.isEmpty()){
   6:         int p = StdIn.readInt();
   7:         int q = StdIn.readInt();
   8:         if(uf.connected(p, q) ) continue;
   9:         uf.union(p, q);
  10:         StdOut.println(p+ " " + q);
  11:     }
  12:     
  13:     StdOut.println(uf.count() + " components");
  14: }

2.2.quick-union算法

   1: /**
   2:  * 以触点p为索引的数组id[p]是p所在的连通分量中的另一个触点q<br>
   3:  * 即p与q是连通的
   4:  * 
   5:  * @author YoungCold
   6:  * 
   7:  */
   8: public class QuickUnionUF extends UF {
   9:  
  10:     public QuickUnionUF(int N) {
  11:         super(N);
  12:     }
  13:  
  14:     /**
  15:      * 找到p的根触点<br>
  16:      * 根触点:符合id[p]=p,即指向自己的触点,即为根触点
  17:      */
  18:     @Override
  19:     public int find(int p) {
  20:         // TODO Auto-generated method stub
  21:         while (p != id[p])
  22:             p = id[p];
  23:         return p;
  24:     }
  25:  
  26:     /**
  27:      * 当p的根触点和q的根触点不同时,说明p和q不在同一个连通分量<br>
  28:      * 要想p和q连通,即将p(q)的根触点(id值为本身)指向q(p)的根触点
  29:      */
  30:     @Override
  31:     public void union(int p, int q) {
  32:         // TODO Auto-generated method stub
  33:         int pRoot = find(p);
  34:         int qRoot = find(q);
  35:  
  36:         if (pRoot == qRoot)
  37:             return;
  38:  
  39:         // 将p的根触点(id值为本身)指向q的根触点
  40:         id[pRoot] = qRoot;
  41:         //每次合并,连通分量的数目减一
  42:         count--;
  43:     }
  44:  
  45:     public static void main(String[] args) {
  46:         DirectInput.directInput(args);
  47:         int N = StdIn.readInt();
  48:         UF uf = new QuickUnionUF(N);
  49:         for (int i = 0; i < N; i++) {
  50:             int p = StdIn.readInt();
  51:             int q = StdIn.readInt();
  52:             if (uf.connected(p, q))
  53:                 continue;
  54:  
  55:             uf.union(p, q);
  56:             StdOut.println(p + " " + q);
  57:         }
  58:         StdOut.println(uf.count() + " components");
  59:     }
  60:  
  61: }

(1)与quick-find不同的是,以触点p为索引的数组id[]不再表示p所在的连通分量,而是表示p所在的连通分量的另一个触点(也可能是它本身),当它是本身时,该触点就是根触点,也就是连通分量所对应的树的根节点,这种联系称之为链接。

(2)森林的表示,实际上id[]数组用父链接的形式表示了一片森林。无论从任何触点所对应的节点开始跟踪链接,最终都能到达含有该节点的树的根节点(可用数学归纳法证明)。

算法分析

1.quick-union算法看似比quick-find算法块,因为它不需要为每对输入遍历整个数组。

2.①最好的情况下find(p),仅访问一次数组,此时触点p为根触点。

②最坏的情况下find(p),访问数组2N-1次

while(p != id[p]) p = id[p];

最坏的情况是触点p所在的连通分量对应的树退化成线性表而且仅有一个连通分量,而p在线性表的表尾。

while()循环的判断条件要访问N次数组,while()循环的执行体要访问N-1 次数组(当最后一次到达根节点时,不执行循环体)。共2N-1次。

3.由此可见,find(p)访问数组的次数,是由触点p对应的节点在树的高度所决定的。设p在树的中的高度为h,则访问数组的次数为2h+1次。

4.假设输入的是有序整数对0-1、0-2、0-3…0-N,N-1对之后的N个触点将全 部处于同一个连通分量内(详见main()),且由quick-union算法得到的树的高度为N-1,其中0→1,1→2…N-1→N。

对于整数对0-i,执行union(0,i),将访问2i+1次数组。

①其中0的根触点是i-1,高度是i-1,根据3,find(0)访问数组2i-1次

②其中i的根触点是i,高度是0,根据3,find(i)访问数组1次

③将i-1的根触点(原指向本身,现指向触点i)的数组内容变成i,访问数组1次

PS:书上是2i+2次,我分析是0-i是连通的,这样0的根触点是i,i的根触点是i,find(0)访问2i+1次,find(i)访问1次

共2i+2次。

可根据main()方法,此时0和i应该不连通才对。

5.处理N对整数所需的所有find()操作访问是;Σ(1→N)(2i) = 2(1+2+…N) ~N2

可以看出quick-union和quick-find都是平方级别的算法。

转载于:https://blog.51cto.com/youngcold/1106992

union-find算法分析(1)相关推荐

  1. union-find算法分析(2)

    2.3.weighted-quick-union--加权quick-union算法 上篇的quick-union算法的效率之所以低(平方级别),最主要的原因是union(p,q)方法,随意将一棵树连接 ...

  2. 『算法』读书笔记 1.4算法分析 Part1

    Chapter 1 本章结构 1.1Java语法 1.2数据抽象 1.3集合类抽象数据类型:背包 (Bags) .队列 (Queues) .栈 (Stacks) 1.4算法分析 1.5连通性问题-Ca ...

  3. 80211 发送速率选择算法分析

    转:https://blog.csdn.net/junglefly/article/details/48974077 1. 介绍 <802.11无线网络权威指南  第二版>中对于选速和降速 ...

  4. 算法 c语言实现 英文版 pdf,数据结构与算法分析++C语言描述++英文版++..pdf-得力文库...

    数据结构与算法分析++C语言描述++英文版++....pdf General Ination 书名数据结构与算法分析 C语言描述 英文版 第2版 作者(美)韦斯著 页数512 出版社机械工业出版社 出 ...

  5. Apriori 算法分析

    Apriori 算法分析: 利用my_new_apriori.py文件,对杂货店商品进行关联规则挖掘,支持度=0.06,置信度=0.2 使用的数据集: 数据集下载地址: 链接:https://pan. ...

  6. Ralink WIFI driver发送速率选择算法分析

    Ralink WIFI driver发送速率选择算法分析 380939960@qq.com 1. 介绍 <802.11无线网络权威指南  第二版>中对于选速和降速的描述: 市面上所有802 ...

  7. 一周搞定期末考系列之《算法分析与设计》

    转眼就到了期末复习算法的时候了 真的是一点都不慌啊 算法分析与设计这门课,由于是一门选修课,而且我对算法分析没有过多的热爱,所以没有对这门课程进行全方位的深度的学习与复习,但是我相信,将下列算法的全部 ...

  8. Python type hints 之 Optional,Union

    1,前言 type hint 在pep484加入,我个人觉得这种类似于类型约束的(机制)有点违背了python简单.简洁的初衷,在慢慢向c# java 这种强类型语言看齐的节奏. 不过好在不强制使用, ...

  9. C++ 共用体union 的使用

    共用体是什么 共用体将不同的数据类型组织为一个整体, 需要注意的是,共用体在同一时刻只能存储一个数据成员的值., 共用体变量的地址和它的格式成员的地址都是同一地址 共用体的一般形式 union 共用体 ...

最新文章

  1. html 消息通知功能,HTML5之消息通知的使用(Web Notification)
  2. [转] Ubuntu/Linux Mint/Debian 安装 Java 8
  3. linux查看硬盘smart_SMART Utility for mac (硬盘检测)
  4. HEU 2036 Paths on a Grid
  5. ssh 连接超时 不断开
  6. mysql和php环境_php环境搭建wampserver、Apache、Mysql和php
  7. Java知识点详解 6 注解
  8. java获取屏幕截图
  9. 暑假第一战——java+mysql 个人信息管理系统
  10. java 安卓 物联网_面向物联网的Android应用开发与实践
  11. python-docx原有图片居中
  12. 期货开户交易所的手续费和查询方法
  13. U-Mail邮件网关智能DNS技术,解决海外邮件接收问题
  14. -转载-我要我们在一起故事原著
  15. 关于“上家公司离职原因”应聘者回答技巧分享
  16. 几种常见的服务器攻击类型
  17. Ubuntu 18.04安装全面战争三国游戏 (by quqi99)
  18. WebView中的视频全屏的相关操作
  19. sitecore系统教程之内容编辑器
  20. MDI窗体的优化---下

热门文章

  1. Android Studio 找不到EventBus/ButterKnife等第三方包解决方案
  2. windbg + sos 调试w3wp进程内存崩溃问题
  3. 【Solr】 solr对拼音搜索和拼音首字母搜索的支持
  4. tcpdump抓包分析具体解释
  5. UVA 11426 GCD-Extreme(II) ★ (欧拉函数)
  6. 串口项目——Cseiralport类的应用(1 )
  7. 装饰工程预结算教程电子书_东北分公司举行工程预结算实战技能培训
  8. NullPointerException int java.util.List.size()
  9. js动态创建对象_JS深浅拷贝的深入浅出
  10. java8 例外网站_Java8兰巴达斯和例外