`
willsunforjava
  • 浏览: 167883 次
  • 性别: Icon_minigender_1
  • 来自: 北京
社区版块
存档分类
最新评论

并查集

 
阅读更多

并查集(union-find set)

并查集是一种树型的数据结构,用于处理一些不相交集合的合并问题。

并查集的主要操作

1. 初始化集合(Make_Set(x))

      把每一个元素初始化为一个集合,初始化后每一个元素的父亲节点是它本身,每一个元素的祖先节点也是它本身(也可以根据情况而变)。

2. 合并不相交的两个集合(Union(x,y))

     合并操作很简单:先设置一个数组Father[x],表示x的“父亲”的编号。那么,合并两个不相交集合的方法就是,找到其中一个集合最父亲的父亲(也就是最久远的祖先),将另外一个集合的最久远的祖先的父亲指向它。

 

 

3. 判断两个元素是否是同一个集合(Find_Set(x))

    本操作可转换为寻找两个元素的最久远祖先是否相同。可以采用递归实现。

 

并查集优化

1. Find_Set(x)时,路径压缩
      寻找祖先时我们一般采用递归查找,但是当元素很多亦或是整棵树变为一条链时,每次Find_Set(x)都是O(n)的复杂度,有没有办法减小这个复杂度呢?
      这就是路径压缩,即当我们经过"递推"找到祖先节点后,"回溯"的时候顺便将它的子孙节点都直接指向祖先,这样以后再次Find_Set(x)时复杂度就变成O(1)了,如下图所示;可见,路径压缩方便了以后的查找。
 


2. Union(x,y)时,按秩合并
   即合并的时候将元素少的集合合并到元素多的集合中,这样合并之后树的高度会相对较小。

主要代码实现
int father[MAX];   /* father[x]表示x的父节点*/
int rank[MAX];     /* rank[x]表示x的秩*/


/* 初始化集合*/
void Make_Set(int x)
{
    father[x] = x; //根据实际情况指定的父节点可变化
    rank[x] = 0;   //根据实际情况初始化秩也有所变化
}


/* 查找x元素所在的集合,回溯时压缩路径*/
int Find_Set(int x)
{
    if (x != father[x])
    {
        father[x] = Find_Set(father[x]); //这个回溯时的压缩路径是精华
    }
    return father[x];
}


/* 
   按秩合并x,y所在的集合
   下面的那个if else结构不是绝对的,具体根据情况变化
   但是,宗旨是不变的即,按秩合并,实时更新秩。
*/
void Union(int x, int y)
{
    x = Find_Set(x);
    y = Find_Set(y);
    if (x == y) return;
    if (rank[x] > rank[y]) 
    {
        father[y] = x;
    }
    else
    {
        if (rank[x] == rank[y])
        {
            rank[y]++;
        }
        father[x] = y;
    }
}
复杂度分析
空间复杂度为O(N),建立一个集合的时间复杂度为O(1),N次合并M查找的时间复杂度为O(M Alpha(N)),这里Alpha是Ackerman函数的某个反函数,在很大的范围内(人类目前观测到的宇宙范围估算有10的80次方个原子,这小于前面所说的范围)这个函数的值可以看成是不大于4的,所以并查集的操作可以看作是线性的。

应用
并查集常作为另一种复杂的数据结构或者算法的存储结构。常见的应用有:求无向图的连通分量个数,最近公共祖先(LCA),带限制的作业排序,实现Kruskar算法求最小生成树等。

经典题目练习

POJ1611

思路:

典型的并查集,最初各自为集,然后每个group进行合并,等到所有的group合并完,题目也就解决了,因为在合并的时候,如果哪两个group中有重合的元素,则那个后来的group会由于按秩合并的原则自动合并到先有的集合当中。
代码:
#include <stdio.h>
#include <stdlib.h>

#define N 30005
int n,m,i,j;
int father[N],num[N];

//初始化各自的father为本身
void MakeSet(int n){
	for(i=0;i<n;i++){
		father[i] = i;
		num[i]=1;
	}
}

//递归的findset
int FindSet(int x){
	if(x != father[x]){
		father[x] = FindSet(father[x]);
	}
	return father[x];
}

void UnionSet(int a,int b){
	int x = FindSet(a);
	int y = FindSet(b);
	if(x == y){
	     return;
	}
	if(num[x] > num[y]){
		father[y] = x;
		num[x] += num[y];
	}else{
		father[x] = y;
		num[y] += num[x];
	}
}

int main(void) {

	while(scanf("%d %d",&n,&m) != EOF && n != 0){
		MakeSet(n);
		for(i=0;i<m;i++){
			int count,first,x;
			scanf("%d %d",&count,&first);
			for(j=1;j<count;j++){
				scanf("%d",&x);
				UnionSet(first,x);
			}
		}
		printf("%d\n",num[FindSet(0)]);
	}
	return EXIT_SUCCESS;
}
 -1做根和使用非递归实现的代码
void MakeSet(int n){
	for(i=0;i<n;i++){
		father[i] = -1;
		num[i]=1;
	}
}

int FindSet(int x){
	while(father[x] != -1){
		x = father[x];
	}
	return x;
}
 

 

 

  • 大小: 11.9 KB
  • 大小: 8.8 KB
分享到:
评论

相关推荐

    数据结构并查集 查询 快速

    数据结构中的并查集(Disjoint Set)是一种用于处理元素集合的分割问题的数据结构,它主要支持两种操作:合并(union)与查找(find)。在实际应用中,尤其是在算法竞赛(ACM)和图论中,它被广泛用于解决快速查询和...

    并查集 团伙数据

    并查集是一种在图论和算法设计中常用的离散数学结构,主要用于处理一些不相交集合的合并与查询问题。这个压缩包文件“团伙数据”显然包含了一些与并查集算法相关的练习数据和可能的题解,目的是帮助学习者更好地理解...

    并查集入门学习并查集

    综上所述,"并查集入门学习并查集"的资源可能是针对初学者的教程,通过“并查集.pdf”这个文档,你将能够深入理解并查集的基本概念、操作原理以及如何在实际问题中应用。对于希望提升算法能力,尤其是参与ACM竞赛的...

    并查集基础知识讲解

    并查集是一种在大型无向图中查找元素所属连通分量的数据结构,常用于解决合并与查询的问题。它的核心思想是将元素组织成一棵树形结构,每个元素都有一个父节点,根节点代表了一个连通分量。并查集的主要操作包括...

    并查集讲义并查集知识学习讲解

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

    并查集 家谱数据

    并查集是一种在图论和算法设计中常用的离散数学结构,主要用来处理一些不相交集合的合并与查询问题。在本数据压缩包中,主题聚焦于家谱数据,可以推断出这些数据可能包含了家庭成员之间的关系,通过并查集这种数据...

    并查集模版

    ### 并查集模版详解 #### 一、并查集简介 并查集是一种用于处理元素集合的动态数据结构,常被应用于图论、计算机网络、数据挖掘等领域。其核心功能是支持两种操作:合并两个集合(并操作)与查询某个元素所属的...

    并查集C++实现

    并查集是一种在大型无向图中查找连接组件的数据结构,它在计算机科学中有着广泛的应用,尤其是在图论和算法设计中。这个压缩包文件"division"可能包含了一个C++实现并查集的示例代码,特别指出是为Visual Studio ...

    经典并查集PPT 这个比较不错啊

    并查集是一种数据结构,主要用于处理一些不相交集合的合并与查询问题。在并查集中,我们将一组对象划分为多个不相交的集合,每个集合由一个代表元素标识。这个数据结构支持两种主要操作: 1. **Find** 操作:查询...

    算法与数据结构:并查集

    并查集是一种用于处理不相交集合操作的数据结构,它主要包含两个基本操作:查找(Find)和合并(Union)。在并查集中,通常用森林的结构来表示各个集合,每棵树代表一个集合,树的根节点代表集合的标识。 **查找...

    优化并查集

    并查集是一种在大型无向图中查找元素所属集合的数据结构,它主要应用于不经常进行连接,但频繁查询是否属于同一集合的问题。在并查集中,我们通常关注两个操作:`Find` 和 `Union`。`Find` 操作用于确定元素所属的...

    最经典并查集详细讲解

    并查集是一种在分散的数据元素中寻找连接关系的数据结构,常用于处理一些不相交集合的合并与查询问题。在图论中,它可以帮助我们快速判断两个节点是否属于同一个连通分量,或者将两个连通分量合并。在本教程中,我们...

    朱全民-并查集ppt

    并查集是一种数据结构,主要用于处理不相交集合的合并与查询问题。它在很多算法竞赛,如信息学奥林匹克竞赛(OI)和全国青少年信息学奥林匹克联赛(NOIP)中有着广泛的应用。朱全民教授的讲解主要围绕并查集的基本...

    并查集模板

    并查集模板并查集模板并查集模板并查集模板并查集模板并查集模板

    并查集算法PKU解题报告

    并查集是一种用于处理集合合并与查询的抽象数据类型,主要应用于解决连通性问题,例如判断图中的两个节点是否在同一连通分量内。在本解题报告中,我们将探讨并查集算法在PKU(北京大学)的三道题目:PKU1182、PKU...

    并查集算法

    深入理解并查集算法,细致讲解,专业老师,一步到位 。

    并查集学习整理 初学者必备

    并查集是一种在图论和数据结构中广泛使用的算法,主要应用于处理不相交集合的合并与查询。在ACM(国际大学生程序设计竞赛)中,掌握并查集的运用对于解决某些特定类型的问题至关重要。这个压缩包包含了全面的并查集...

    并查集算法思想的算法

    ### 并查集算法思想详解 #### 一、并查集基本概念 并查集是一种数据结构,主要用于处理一些不交集的合并及查询问题,它支持两种操作: 1. **合并**(Union):将两个不同的集合合并成一个集合。 2. **查找**...

    并查集C/C++代码实现

    ### 并查集C/C++代码实现 #### 知识点概述 并查集是一种用于处理元素集合的动态集合问题的数据结构,它支持两种基本的操作:**并**和**查**。并查集的主要用途是判断一个元素是否属于某个集合,并且能够有效地将两...

Global site tag (gtag.js) - Google Analytics