相同是查找一个图是否有环的算法,可是这个算法非常牛逼,构造树的时候能够达到O(lgn)时间效率。n代表顶点数

原因是依据须要缩减了树的高度,也叫压缩路径(Path compression),名字非常高深,只是事实上不难理解,简单来说就是每次查找一个节点的时候,都把这一路径中的全部节点都赋予根节点作为路径。

原文没指出的地方:

也由于须要压缩,所以初始化的时候注意,不能如前面简单有用Union Find的算法那样初始化全部顶点的父母节点为-1,应该是初始化全部节点的父母节点为本身(自己生殖自己?),然后就方便递归的时候一律能够返回这个跟节点了。

当然事实上初始化为-1也是能够的,只是须要额外代码处理一下,也不难。

最后能够參考原文:http://www.geeksforgeeks.org/union-find-algorithm-set-2-union-by-rank/

#pragma once
#include <iostream> class UnionFindUnionByRank
{
struct Edge
{
int src, des;
}; struct Graph
{
int V, E;
Edge *edges;
Graph(int v, int e) : V(v), E(e)
{
edges = new Edge[e];
}
~Graph()
{
if (edges) delete [] edges;
}
}; struct subSet
{
int parent, rank;
}; int find(subSet *subs, int i)
{
//由于要压缩,所以不能使用-1作为根的标志了
if (subs[i].parent != i)
{
//Union by rank: attach smaller rank tree to high rank tree. It is so simple, but very hard to create it totally by ourself, so it's good to stand on the shoulder of the giant.
subs[i].parent = find(subs, subs[i].parent);
}
return subs[i].parent;//由于假设-1作为根标志,那么这里就要返回i,就达不到压缩的效果了,而是应该返回parent,一层一层递归回上一层。
} void unionTwo(subSet *subs, int x, int y)
{
int xroot = find(subs, x);
int yroot = find(subs, y); if (subs[xroot].rank < subs[yroot].rank)
{
subs[xroot].parent = yroot;
}
else if (subs[xroot].rank > subs[yroot].rank)
{
subs[yroot].parent = xroot;
}
else
{
//only need to increment its rank when ther are equal rank
subs[yroot].parent = xroot;
subs[xroot].rank++;
}
} bool isCycle(Graph *gra)
{
subSet *subs = new subSet[gra->V];
for (int i = 0; i < gra->V; i++)
{
subs[i].parent = i;//parent不能初始化为-1
subs[i].rank = 0;
} for (int e = 0; e < gra->E; e++)
{
int x = find(subs, gra->edges[e].src);
int y = find(subs, gra->edges[e].des); if (x == y) return true; unionTwo(subs, x, y);
} return false;
}
public:
UnionFindUnionByRank()
{
int V = 3, E = 3;
struct Graph* graph = new Graph(V, E); // add edge 0-1
graph->edges[0].src = 0;
graph->edges[0].des = 1; // add edge 1-2
graph->edges[1].src = 1;
graph->edges[1].des = 2; // add edge 0-2
graph->edges[2].src = 0;
graph->edges[2].des = 2; if (isCycle(graph))
printf( "Union By Rank found graph contains cycle \n" );
else
printf( "Union By Rank found graph doesn't contain cycle \n" );
}
};

Geeks Union-Find Algorithm Union By Rank and Path Compression 图环算法的更多相关文章

  1. 转 SQL Union和SQL Union All两者用法区别效率以及与order by 和 group by配合问题

    SQL Union和SQL Union All两者用法区别效率以及与order by 和 group by配合问题 SQL Union和SQL Union All用法 SQL UNION 操作符 UN ...

  2. 关于UNION ALL与 UNION 用法和区别

    (转自:http://www.cnblogs.com/EricaMIN1987_IT/archive/2011/01/20/1940188.html) UNION指令的目的是将两个SQL语句的结果合并 ...

  3. SQL Union和SQL Union All用法

    SQL UNION 操作符 UNION 操作符用于合并两个或多个 SELECT 语句的结果集. 请注意,UNION 内部的 SELECT 语句必须拥有相同数量的列.列也必须拥有相似的数据类型.同时,每 ...

  4. union 和 all union

    sql union用法和sql union all用法,sql union效率 1.sql union用法 sql union在查询中可以将两个SQL 语句的结果合并起来.如果这样看的话, UNION ...

  5. 从Random Walk谈到Bacterial foraging optimization algorithm(BFOA),再谈到Ramdom Walk Graph Segmentation图分割算法

    1. 从细菌的趋化性谈起 0x1:物质化学浓度梯度 类似于概率分布中概率密度的概念.在溶液中存在不同的浓度区域. 如放一颗糖在水盆里,糖慢慢溶于水,糖附近的水含糖量比远离糖的水含糖量要高,也就是糖附近 ...

  6. UNion ALL 和 UNION 的区别

    UNION: 指定合并多个结果集并将其作为单个结果集返回.ALL: 将全部行并入结果中.其中包括重复行.如果未指定该参数,则删除重复行.

  7. linq 多个left join 和 sql union all -> linq union 方法

     (   from s in Base_SysMenus   join r in Base_RoleRights on s.Menu_Id equals r.Menu_Id into temp   f ...

  8. UNION ALL vs UNION

    一直没意识到它们之间的区别,只知道UNION ALL在性能上优于UNION,忽略一个很重要的区别:UNION会去掉重复的行,而UNION ALL是包括所有行.

  9. [Union]C++中Union学习笔记

    C++ union结构式一种特殊的类.它能够包含访问权限.成员变量.成员函数(可以包含构造函数和析构函数).它不能包含虚函数和静态数据变量.它也不能被用作其他类的基类,它本身也不能有从某个基类派生而来 ...

随机推荐

  1. ExtJs 起始日期 结束日期 验证

    Ext.apply(Ext.form.VTypes,{ daterange: function(val, field) { var date = field.parseDate(val); // We ...

  2. 如何下载android源码与android内核源码

    首先,要分清楚,android的源代码和android的内核代码一般是分开的,要分别进行下载. 1.先下载android的源代码.(这里不包括android的内核代码)      下载最新的源代码,一 ...

  3. 3种方式实现KVO并进行对比

    KVO KVO属于设计模式中的观察者模式,在观察者模式中,一个对象任何状态的变更都会通知另外的对改变感兴趣的对象.这些对象之间不需要知道彼此的存在,这其实是一种松耦合的设计.当某个属性变化的时候,我们 ...

  4. MAC之tar解压与压缩打包命令

    tar [-cxtzjvfpPN] 文件与目录 ....参数:-c :建立一个压缩文件的参数指令(create 的意思):-x :解开一个压缩文件的参数指令!-t :查看 tarfile 里面的文件! ...

  5. 触发器系列(2) DataTrigger

    触发条件: DataTrigger是以控件DataContext的属性作为触发条件 本例效果说明: <!--当值为1时将外边框的背景色改为黑色--> <!--当值为2时 改变透明度达 ...

  6. 使用HTML5画饼图

    在进行数据的统计分析时, 饼图也是比较经常用到的一类统计图. 需求分析:   一个饼图一般包含以下几部分:   1.标题   2.扇形   3.份额(百分比)   4.标识器      设计:     ...

  7. 【BZOJ】【1419】Red is good

    数学期望/期望DP 还是戳<浅析竞赛中一类数学期望问题的解决方法>这篇论文…… $$ f[i][j]= \begin{cases} 0 &, &i==0 \\ f[i-1] ...

  8. OTL翻译(7) -- otl_exception类

    otl_exception 这个类是OTL用来抛出异常的类.如果数据库API返回一个非0的错误值,则OTL会将会抛出一个otl_exception的异常.一个otl_exception异常有可能是一个 ...

  9. VUE router-view 页面布局 (嵌套路由+命名视图)

    嵌套路由 实际生活中的应用界面,通常由多层嵌套的组件组合而成.同样地,URL 中各段动态路径也按某种结构对应嵌套的各层组件,例如: /user/foo/profile /user/foo/posts ...

  10. 同一页面的不同Iframe获取数据

    公共父页面(主页面): <%@ page language="java" import="java.util.*" pageEncoding=" ...