描述:

并查集是一种描述解决等价关系。能够方便地描述不相交的多个集合。

支持如下操作    1. 建立包含元素 x 的集合  MakeSet(x)

2. 查找给定元素所在的集合 Find(x), 返回所在集合的代表

3. 将两个不相交的集合合并 Union(s1, s2)

本文参考《数据结构与算法分析,C语言描述》这本书,利用数组,给出了并查集的一个容易实现的版本。

采用了按秩合并 和 路径压缩 的方法加速。

数据结构:

用树表示一个集合,树的跟节点就是这个集合的代表元素。

并采用一维数组来非显示地模拟这个森林:

1. 数组长度是总的集合元素个数;

2. s[i] 表示元素 i 的父亲节点;

3. 如果 s[i] 是 负数,表示 i 就是代表元素; 并且负数的绝对值表示所在树的高度。(按高度压缩)

在这样的定义下,Find(x) 非常容易实现,只要从元素 x, 不断往上找,直到找到根节点返回即可。

// return the disjoint set which x belongs to
SetType Find(ElementType x, DisJointSet s)
{
if(s[x] < 0)
return x;
else
return Find(s[x], s);
}

按高度合并:

注意到,Find(x) 的复杂度是树的高度。

按高度合并就是通过将 矮的树 合并到 高的树作为其孩子,从而避免树过高。

//Assume root1 and root2 are roots
void SetUnion(DisJointSet s, SetType root1, SetType root2)
{
if(s[root1] <= s[root2])//root1 is deeper than root2
{
if(s[root1] == s[root2])
s[root1] --;
s[root2] = root1;
}
else
{
s[root1] = root2;
}
}

路径压缩:

这种方法可以与按高度合并兼容,能够得到较高的效率。

它其实是在 Find(x) 这个函数做文章。

在搜索 x 所在树的 root 节点的过程中,将中途的节点都指向 root.

看了下图,大家就能明白了。

代码非常简单:

// return the disjoint set which x belongs to
SetType Find(ElementType x, DisJointSet s)
{
if(s[x] < 0)
return x;
else
return s[x] = Find(s[x], s);
}

完整的代码如下:

/* dis-joint-set implemented by L.J. in Nov.11, 2013 */
/* union by height */
#include "disjointset.h"
#include <iostream>
using namespace std; const int NumSets = 8;
typedef int DisJointSet[ NumSets + 1];
typedef int SetType;
typedef int ElementType; void Initialize(DisJointSet s)
{
for(int i=NumSets; i>0; --i)
s[i] = 0;
} //Assume root1 and root2 are roots
void SetUnion(DisJointSet s, SetType root1, SetType root2)
{
if(s[root1] <= s[root2])//roo1 is deeper than root2
{
if(s[root1] == s[root2])
s[root1] --;
s[root2] = root1;
}
else
{
s[root1] = root2;
}
} // return the disjoint set which x belongs to
SetType Find(ElementType x, DisJointSet s)
{
if(s[x] < 0)
return x;
else
return Find(s[x], s);
}

数据结构《14》----并查集 Union-Find的更多相关文章

  1. 数据结构之并查集Union-Find Sets

    1.  概述 并查集(Disjoint set或者Union-find set)是一种树型的数据结构,常用于处理一些不相交集合(Disjoint Sets)的合并及查询问题. 2.  基本操作 并查集 ...

  2. 数据结构 之 并查集(Disjoint Set)

    一.并查集的概念:     首先,为了引出并查集,先介绍几个概念:     1.等价关系(Equivalent Relation)     自反性.对称性.传递性.     如果a和b存在等价关系,记 ...

  3. 数据结构09—— 并查集(Union-Find)

    一.关于并查集 并查集(Union-Find)是一种树型的数据结构,常用于处理一些不相交集合(Disjoint Sets)的合并及查询问题.并查集(Union-Find)从名字可以看出,主要它涉及两种 ...

  4. 并查集(Union/Find)模板及详解

    概念: 并查集是一种非常精巧而实用的数据结构,它主要用于处理一些不相交集合的合并问题.一些常见的用途有求连通子图.求最小生成树的Kruskal 算法和求最近公共祖先等. 操作: 并查集的基本操作有两个 ...

  5. 【基本数据结构】并查集-C++

    并查集,在一些有N个元素的集合应用问题中,我们通常是在开始时让每个元素构成一个单元素的集合,然后按一定顺序将属于同一组的元素所在的集合合并,其间要反复查找一个元素在哪个集合中.这一类问题近几年来反复出 ...

  6. 数据结构(并查集||树链剖分):HEOI 2016 tree

    [注意事项] 为了体现增强版,题目限制和数据范围有所增强: 时间限制:1.5s 内存限制:128MB 对于15% 的数据,1<=N,Q<=1000. 对于35% 的数据,1<=N,Q ...

  7. POJ 1611 The Suspects 并查集 Union Find

    本题也是个标准的并查集题解. 操作完并查集之后,就是要找和0节点在同一个集合的元素有多少. 注意这个操作,须要先找到0的父母节点.然后查找有多少个节点的额父母节点和0的父母节点同样. 这个时候须要对每 ...

  8. 【算法与数据结构】并查集 Disjoint Set

    并查集(Disjoint Set)用来判断已有的数据是否构成环. 在构造图的最小生成树(Minimum Spanning Tree)时,如果采用 Kruskal 算法,每次添加最短路径前,需要先用并查 ...

  9. 【简单数据结构】并查集--洛谷 P1111

    题目背景 AA地区在地震过后,连接所有村庄的公路都造成了损坏而无法通车.政府派人修复这些公路. 题目描述 给出A地区的村庄数NN,和公路数MM,公路是双向的.并告诉你每条公路的连着哪两个村庄,并告诉你 ...

  10. Java 并查集Union Find

    对于一组数据,主要支持两种动作: union isConnected public interface UF { int getSize(); boolean isConnected(int p,in ...

随机推荐

  1. linux服务器挂载第二块磁盘图文解说

    文章来源:http://www.cndns.com/help/help_con.aspx?hid=394 Linux磁盘挂载是比较常见的管理操作之一.我司橙云预装的linux系统有2块盘,一块为系统盘 ...

  2. MyBatis实体类映射文件模板

      <?xml version="1.0" encoding="UTF-8" ?> <!DOCTYPE mapper PUBLIC " ...

  3. web基础之hibernate(一篇)

    hibernate的一些基本的认识 1.       hibenate是一个框架(framework) 2.       hibernate是一个orm框架 3.       orm(object r ...

  4. hdu-------(1698)Just a Hook(线段树区间更新)

    Just a Hook Time Limit: 4000/2000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)Total ...

  5. Java 集合系列 02 Collection架构

    java 集合系列目录: Java 集合系列 01 总体框架 Java 集合系列 02 Collection架构 Java 集合系列 03 ArrayList详细介绍(源码解析)和使用示例 Java ...

  6. C++文件读写练习

    编写一个程序,统计data.txt文件的行数,并将所有行前加上行号后写到data1.txt文件中. 算法提示: 行与行之间以回车符分隔,而getline()函数以回车符作为终止符.因此,可以采用get ...

  7. HDU 5773 The All-purpose Zero 求LIS

    求最长上升子序列长度: 单纯的dp时间复杂度是O(n*n)的 dp[i] = max(dp[j]+1); (0=<j<=i-1 && a[i]>a[j]) 用二分可以 ...

  8. java引用类型

      java数据类型图: java的数据类型分基本数据类型(原始数据类型)和引用数据类型:1.基本八大类,图中可以很清楚的看到:这种类型的数据变量在声明之后java就会立刻分配给他内存空间.如:sho ...

  9. 数组越界保护与消息传递black机制

    数组越界保护if(index.row <= [array count]) 发送消息[[NSNotificationCenter defaultCenter]     postNotificati ...

  10. centos下cmake安装

    步骤一.安装gcc等必备程序包(已安装则略过此步,用gcc -v检测) yum install -y gcc gcc-c++ make automake 步骤二.安装wget (已安装则略过此步) y ...