Union-Find 算法实现

Union-Find

问题描述:

给定一个n个序列的对象,有两种操作:

-Union command:连接两个对象;

-Find/connected query:两个对象是否连接(有路径)

算法实现方式

1.用一个数组保存着每个对象所在的connected component,这种方式可以快速进行FIND,但是在union操作时需要遍历整个对象数组

2.利用树的观点,在数组中保存每个对象节点的parent,这个每个connected component就是一棵树,这种方式union很高效,只需要更新相应节点的parent即可,但是在find的时候可能就会遍历整个树,特别是当一棵树比较高的时候。

3.在上述2中实现union(p,q)的时候,我们用一种特定的方式将p所在的树的置为q所在树的孩子,没有考虑到树的大小,就会导致严重失衡的情况。Weighted quick-union 引入一个新的数组来保存每棵树的尺寸,总是将小树链入到大树下,实现相对的平衡。

4.利用path compression进一步对上述算法进行优化,在每一次root操作的时候,不单单只是追溯查询一个节点的根,而是动态的将其根节点往上推进。从而使得           component tree 越来越平坦化。  如下要查询节点6的根节点,在查询的最后会更新6直接指向根节点。

接下来会把3,1分别指针指向root

具体代码

--------1

//这种方式可以快速判断是否相连,但是union操作需要遍历整个对象数组

public class QuickFindUF
{

// 这个数组保存着这个N个节点的所在分组

private int[] id ;

public QuickFindUF( int n)
{

id = new int [n];

for (int i =
0; i < n; i ++) {

id[ i]
= i ;

}

}

public boolean find(int p, int q)
{

return id [p]
== id [q];

}

// 连接p,q节点的时候,要将p所在component中的所有节点的id更新

public void union(int p, int q)
{

int pid
= id [p];

int qid
= id [q];

for (int i
= 0; i < id.length;
i++) {

if (id [i]
== pid)

id[i]
= qid;

}

}

}

-----------2

//这种方式可以快速实现俩个

public class QuickUnionUF
{

// 这个数组保存着该对象的parent

private int[] id ;

public QuickUnionUF( int n)
{

id = new int [n];

for (int i
= 0; i < n; i++) {

id[i]
= i;

}

}

// 辅助函数,追溯节点的n的根

private int root(int n)
{

while (n
!= id [n])

n = id[n];

return n;

}

public boolean find(int p, int q)
{

return root(p)
== root(q);

}

// 连接p,q节点的时候,要将p的parent的parent更新为q的parent

public void union(int p, int q)
{

int parentp
= id [p];

int parentq
= id [q];

id[parentp]
= parentq;

}

}

---------------3

public class WeightedQuickUnionUF
{

private int[] id ; //
id[i] = parent of i

private int[] sz ; // sz[i]
= number of objs in subtree rooted at i

private int count ; // num of
components

public WeightedQuickUnionUF( int N)
{

count =
N;

id = new int [N];

sz = new int [N];

for (int i
= 0; i < N; i++) {

id[i]
= i;

sz[i]
= 1;

}

}

public int count()
{

return count ;

}

// 得到包含这个对象的component的ID,也就是根节点

public int root(int p)
{

while (p
!= id [p])

p = id[p];

return p;

}

public boolean connected(int p, int q)
{

return root(p)
== root(q);

}

// 合并包含p,q的两个components,会考虑树的大小

public void union(int p, int q)
{

int rootP
= root(p);

int rootQ
= root(q);

if (rootP
== rootQ)

return;

if (sz [rootP]
< sz[rootQ]) {

id[rootP]
= rootQ;

sz[rootQ]
+= sz[rootP];

else {

id[rootQ]
= rootP;

sz[rootP]
+= sz[rootQ];

}

}

}

----------------4

public class WeightedQuickUnionWitchPathCompression
{

private int[] id ; //
id[i] = parent of i

private int[] sz ; // sz[i]
= number of objs in subtree rooted at i

private int count ; // num of
components

public WeightedQuickUnionWitchPathCompression( int N)
{

count =
N;

id = new int [N];

sz = new int [N];

for (int i
= 0; i < N; i++) {

id[i]
= i;

sz[i]
= 1;

}

}

public int count()
{

return count ;

}

// path compression实现在这里。

public int root(int p)
{

int root
= p;

while (root
!= id [root])

root = id[root];

// 会将p以上的节点全部指向root

while (p
!= root) {

int newp
= id [p];

id[p]
= root;

p = newp;

}

return root;

}

public boolean connected(int p, int q)
{

return root(p)
== root(q);

}

// 合并包含p,q的两个components,会考虑树的大小

public void union(int p, int q)
{

int rootP =
root(p);

int rootQ
= root(q);

if (rootP ==
rootQ)

return;

if (sz [rootP ]
< sz [rootQ]) {

id[ rootP]
= rootQ;

sz[rootQ]
+= sz[ rootP];

else {

id[rootQ]
= rootP;

sz[ rootP]
+= sz[rootQ];

}

}

}

备注:参考普林斯顿大学《算法,part I》

Union-Find 算法实现

时间: 2024-11-08 01:41:31

Union-Find 算法实现的相关文章

HDU 3635 Dragon Balls 七龙珠 Union Find算法

孙悟空要寻找七龙珠,这回是七龙珠的增强版了,因为这些龙珠会衍生,最后不止七颗龙珠了. 悟空带着布玛的龙珠雷达探测器出发了,却发现布玛的龙珠雷达探测器的程序太垃圾了,所以找到我们这些ACM高手为龙珠雷达探测器写个程序,要求可以显示某颗龙珠所在的城市的位置,该龙珠所在的城市共有多少颗龙珠,龙珠移动过的次数. 布玛是个有钱人啊,写个程序我要价5百万,不算过分吧.因为本程序需要用到Union Find(并查集)算法,而且最困难的部分是如何压缩路径,不压缩路径自然容易做到,要压缩路径可以使得程序加快很多,

Union-Find算法小结

对Union Find算法不熟悉,可参看 http://blog.csdn.net/dm_vincent/article/details/7655764 http://blog.csdn.net/dm_vincent/article/details/7769159 个人觉得该博文阐述非常通俗易懂,第二个链接是博主举的几个应用例子. 几个需要思考的问题: 这种算法通常应用于什么场景?怎么用? 如何将问题归约到union-find或者说union的目的是什么? 怎么union,即两个元素满足什么条件

图论(五)------最小生成树

一个无向图G的最小生成树就是由该图的那些连接了G的所有顶点的边构成的树,且其总权重最低.最小生成树存在当且仅当G是连通的. 对于任何一生成树T,如果将一条不属于T的边e加进来,则产生一个圈.如果从圈中除去任意一条边,则又恢复树的特性.如果边e的权值比除去的边的值低,那么新生成的树的值就比原生成的树的值低.如果在建立树T的过程中每次添加的边在所有避免成圈的边中值最小,那么最后得到的生成树的值不能再改进.对于最小生成树的贪婪算法是成立的. 算法策略 在每一个步骤中都形成最小生成树的一条边.算法维护一

Leetcode 305. Number of Islands II

Problem: A 2d grid map of m rows and n columns is initially filled with water. We may perform an addLand operation which turns the water at position (row, col) into a land. Given a list of positions to operate, count the number of islands after each

MySQL 优化之 index_merge (索引合并)

深入理解 index merge 是使用索引进行优化的重要基础之一.理解了 index merge 技术,我们才知道应该如何在表上建立索引. 1. 为什么会有index merge 我们的 where 中可能有多个条件(或者join)涉及到多个字段,它们之间进行 AND 或者 OR,那么此时就有可能会使用到 index merge 技术.index merge 技术如果简单的说,其实就是:对多个索引分别进行条件扫描,然后将它们各自的结果进行合并(intersect/union). MySQL5.

Union-Find(并查集): Quick union算法

Quick union算法 Quick union: Java implementation Quick union 性能分析 在最坏的情况下,quick-union的find root操作cost(访问array的次数)会达到N. 所以quick-union的性能也不好.

Geeks Union-Find Algorithm Union By Rank and Path Compression 图环算法

同样是查找一个图是否有环的算法,但是这个算法很牛逼,构造树的时候可以达到O(lgn)时间效率.n代表顶点数 原因是根据需要缩减了树的高度,也叫压缩路径(Path compression),名字很高深,不过其实不难理解,简单来说就是每次查找一个节点的时候,都把这一路径中的所有节点都赋予根节点作为路径. 原文没指出的地方: 也因为需要压缩,所以初始化的时候注意,不能如前面简单实用Union Find的算法那样初始化所有顶点的父母节点为-1,应该是初始化所有节点的父母节点为本身(自己繁殖自己?),然后

联合查找算法Union Find的一些分析

最近在学习Robert  Sedgewic,Kevin  Wayne的Algorithms第四版,谈谈有关并查集的概念. 首先,我们知道并查集是一种树型的数据结构,用于处理一些不相交集合,而最重要的就是联合查找算法,Union Find. 并查集的基本操作: makeSet(s):建立一个新的并查集,其中包含 s 个单元素集合. unionSet(x, y):把元素 x 和元素 y 所在的集合合并,要求 x 和 y 所在的集合不相交,如果相交则不合并. find(x):找到元素 x 所在的集合的

&lt;算法&gt;&lt;Union Find并查集&gt;

Intro 想象这样的应用场景:给定一些点,随着程序输入,不断地添加点之间的连通关系(边),整个图的连通关系也在变化.这时候我们如何维护整个图的连通性(即判断任意两个点之间的连通性)呢? 一个比较简单的solution是每个点都有一个便签,标记它属于哪个连通子图.这种做法就有一个很明显的问题 -- 牵一发而动全身,因为每个节点所属的组号(标签)都是单独记录,各自为政的,没有将它们以更好的方式组织起来,当涉及到修改的时候,除了逐一通知.修改,别无他法.所以现在的问题就变成了,如何将节点以更好的方式

基于Spark MLlib平台的协同过滤算法---电影推荐系统

基于Spark MLlib平台的协同过滤算法---电影推荐系统 又好一阵子没有写文章了,阿弥陀佛...最近项目中要做理财推荐,所以,回过头来回顾一下协同过滤算法在推荐系统中的应用. 说到推荐系统,大家可能立马会想到协同过滤算法.本文基于Spark MLlib平台实现一个向用户推荐电影的简单应用.其中,主要包括三部分内容: 协同过滤算法概述 基于模型的协同过滤应用---电影推荐 实时推荐架构分析     一.协同过滤算法概述 本人对算法的研究,目前还不是很深入,这里简单的介绍下其工作原理. 通常,