发展一个有效算法的具体(一般)过程:

union-find用来解决dynamic connectivity,下面主要讲quick find和quick union及其应用和改进。

基本操作:find/connected queries和union commands

动态连接性问题的场景:

1.1  建立模型(Model the problem):

关于object:0-N-1

关于连接的等价性:

关于连接块:

关于基本操作find query和union command:

比如union操作:

目标:

练习:

答案:C。最后剩下的连接块有{0,5,6}{3,4}{1,2,7,8,9}。

1.2  算法及其改进(Algorithm and improvement):

1.2.1  Quick Find

实现过程:

 public class QuickFindUF
{
private int[] id; public QuickFindUF(int N)
{
id = new int[N];
for (int i = 0; i < N; i++)
id[i] = i;
} 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];
for (int i = 0; i < id.length; i++)
//这里有个约定:
//p和q联合的时候,所有和p是一个连接块(connected conponents)的点的id都要设置为与id[q]相等
if (id[i] == pid) id[i] = qid;
}
}

各个函数的时间复杂度:

弊端:

对N个实体做N次的union操作,时间复杂度是O(N2)。换言之,Quick find太慢,不适合大量的数据。

练习:

答案:C。最差情况就是除了id[q],其他元素都要改变。

1.2.2  Quick Union

说明:

实现过程:

 public class QuickUnionUF
{
private int[] id;//id[i],节点i的父节点 public QuickFindUF(int N)
{
id = new int[N];
//划分为N棵子树,每个子树的根节点就是本身
for (int i = 0; i < N; i++)
id[i] = i;
} private int root(int i)//找打i所在子树的根节点
{
//如果id[i] == i,说明i是某一棵子树的根节点
while (i != id[i]) i = id[i];
return i;
} public boolean connected(int p, int q)
{
return root(p) == root(q);
} public void union(int p, int q)//将p所在子树的根节点的父节点设为q所在子树的根节点
{
int i = root(p);
int j = root(q);
id[i] = j;
}
}

各个操作的时间复杂度:注意quick union的union和find是最差情况(例如,形成的子树很高)的时间复杂度。

弊端:

练习:

答案:D。3的根节点是6:3->5->2->6。7的根节点是6:7->1->9->5->2->6。

练习:

答案:C

1.2.3  Weighted quick union

Improvement 1:weighting。为每个树保留track记录树的规模;union的时候将规模小的树的根节点添加为规模大的树的根节点的子节点。主要针对Quick union中容易出现树很高的情况。

实现过程:

 public class WeightedQuickUnionUF {
private int[] id,sz; public WeightedQuickUnionUF(int N)
{
id = new int[N];
sz = new int[N];//记录以i为根节点的树的节点个数
for (int i = 0; i < N; i++)
{
sz[i] = 1;
id[i] = i;
}
} private int root(int i)//和quick union相同
{
while (i != id[i]) i = id[i];
return i;
} public boolean connected(int p, int q)//和quick union相同
{
return root(p) == root(q);
} public void union(int p, int q)
{
int i = root(p);
int j = root(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];}
}
}

各个函数的时间复杂度:注意到weighted quick union中的union和connected操作的时间复杂度都是log2N。

命题:按照Weighted quick union实现的树的任意一个节点的深度不会超过log2N。

证明:关注任意节点x。

1. 只有当包含x的子树T1作为lower tree被合并的时候,x的深度才有可能增加1。

2. 另一棵树T2,其中sz[T2]>=sz[T1]。

每合并1次,树的规模*2,并且最后的树的规模==N,所以x最多只能增加log2N次,意味着节点x最后的深度不会超过log2N。

Weighted quick union和Quick union的比较实例:

Weighted quick union实现结果更加均衡,叶节点到根的距离最大为4,每个节点到根节点的距离的平均要远远小于Quick union的结果。

1.2.4 Weighted quick union with path compressioin

Improvement 2:path compression。就是路径压缩。

实现过程有2种方式:主要区别是root函数的实现。

1. 找到当前点x的根节点后,将x与根节点相连路径上的所有节点的父节点设为根节点。

2. 在寻找当前点x的根节点的过程中,直接将x的父节点设置为x的父节点的父节点。

下面只展示union函数的实现:

方式1:

 private int root(int i)
{
if (id[i] == i) return i;//只有指向根节点才返回
return id[i] = root(id[i]);
}

方式2:

     private int root(int i)
{
while (i != id[i])
{
id[i] = id[id[i]];//指向父节点的父节点
i = id[i];
}
return i;
}

对N个点使用Weighted quick union with path compressioin中的union find操作m次的时间复杂度:

关于lg*的解释:http://stackoverflow.com/questions/2387656/what-is-olog-n/2387669

log* (n)- "log Star n" as known as "Iterated logarithm"

In simple word you can assume log* (n)= log(log(log(.....(log* (n))))

已经证明,union find问题的时间复杂度不可能到O(N)。

练习:

答案:

总结:

Algorithm partI 第2节课 Union−Find的更多相关文章

  1. centos DNS服务搭建 DNS原理 使用bind搭建DNS服务器 配置DNS转发 配置主从 安装dig工具 DHCP dhclient 各种域名解析记录 mydns DNS动态更新 第三十节课

    centos  DNS服务搭建  DNS原理  使用bind搭建DNS服务器 配置DNS转发 配置主从  安装dig工具  DHCP  dhclient  各种域名解析记录  mydns DNS动态更 ...

  2. 风炫安全Web安全学习第十六节课 高权限sql注入getshell

    风炫安全Web安全学习第十六节课 高权限sql注入getshell sql高权限getshell 前提条件: 需要知道目标网站绝对路径 目录具有写的权限 需要当前数据库用户开启了secure_file ...

  3. centos linux安全和调优 第四十一节课

    centos  linux安全和调优    第四十一节课 上半节课 Linux安全 下半节课 Linux调优 2015-07-01linux安全和调优 [复制链接]--http://www.apele ...

  4. centos shell编程6一些工作中实践脚本 nagios监控脚本 自定义zabbix脚本 mysql备份脚本 zabbix错误日志 直接送给bc做计算 gzip innobackupex/Xtrabackup 第四十节课

    centos   shell编程6一些工作中实践脚本   nagios监控脚本 自定义zabbix脚本 mysql备份脚本 zabbix错误日志  直接送给bc做计算  gzip  innobacku ...

  5. [iOS]Objective-C 第一节课

    Objective-C 第一节课 本节课的主要内容 创建Objective-C的第一个工程 HelloWorld Objective-C中的字符串 创建Objective-C的第一个工程 打开Xcod ...

  6. 《从零玩转python+人工智能-3》120,122节课深度优先疑问解答

     深度优先(从左往右): 按照这个原则来:至于使用栈,或者队列:根据它们不同的特性:最终务必保证最终结果是原继承结构的“从左往右”:所以,如果是栈,就是右侧先入栈,左侧再入(这样左侧能先出来,遵循从左 ...

  7. [转][南京米联ZYNQ深入浅出]第二季更新完毕课程共计16节课

    [南京米联]ZYNQ第二季更新完毕课程共计16节课 [第二季ZYNQ]                                                                  ...

  8. SpringBoot常用Starter介绍和整合模板引擎Freemaker、thymeleaf 4节课

    1.SpringBoot Starter讲解 简介:介绍什么是SpringBoot Starter和主要作用 1.官网地址:https://docs.spring.io/spring-boot/doc ...

  9. centos mysql 实战 第一节课 安全加固 mysql安装

    centos mysql  实战  第一节课   安全加固  mysql安装 percona名字的由来=consultation 顾问+performance 性能=per  con  a mysql ...

随机推荐

  1. zabbix监控cpu jumps

    cpu监控图形分为三种 cpu jumps cpu突发 包含 context switches per second 进程线程切换 interrupts per second 每秒的中断次数 cpu ...

  2. day14(带参装饰器,迭代器,生成器,枚举对象)

    一,复习 ''' 函数的嵌套定义:在函数内部定义另一个函数 闭包:被嵌套的函数 -- 1.外层通过形参给内层函数传参 -- 2.验证执行 开放封闭原则: 功能可以拓展,但源代码与调用方式都不可以改变 ...

  3. ASP.NET:邮件服务器与客户端

    目录: 一.概述 二.MX设置 三.使用系统的SMTP功能发邮件 四.使用hMailServer收发邮件 五.Web邮件客户端 一.概述 首先必须清楚SMTP才是提供邮件服务器的核心,收发邮件全靠SM ...

  4. Linux Socket - 内核非阻塞功能

    select 函数 int select(int maxfdp,fd_set *readfds,fd_set *writefds,fd_set *errorfds,struct timeval*tim ...

  5. 【转】敏捷开发之Scrum扫盲篇

    现在敏捷开发是越来越火了,人人都在谈敏捷,人人都在学习Scrum和XP... 为了不落后他人,于是我也开始学习Scrum,今天主要是对我最近阅读的相关资料,根据自己的理解,用自己的话来讲述Scrum中 ...

  6. R语言中Fisher判别的使用方法

    最近编写了Fisher判别的相关代码时,需要与已有软件比照结果以确定自己代码的正确性,于是找到了安装方便且免费的R.这里把R中进行Fisher判别的方法记录下来. 1. 判别分析与Fisher判别 不 ...

  7. .NET处理HTTP请求

    第一种:使用HttpWebRequest string result = ""; HttpWebRequest request = (HttpWebRequest)WebReque ...

  8. 比特币的TxHash为什么会发生改变

    比特币中TxHash为什么会变化? 一直不理解比特币的Tx在被打包确认之前TxHash为什么会发生变化,这次终于找到了依据. 交易可延展性 虽然交易签名后,签名当前不会覆盖经过哈希处理以创建事务哈希的 ...

  9. Android / iOS 招聘

    1. 面试题 https://github.com/ChenYilong/iOSInterviewQuestions 2. 一些不错的idea CDI - Développeur iOS/Androi ...

  10. ADV拍卖

    #include <stdio.h> int ren,wuping; int qian[20]; int wu1[20],wu2[20],wu3[20]; int a[20],visit[ ...