并查集的基本介绍

来源:互联网 发布:java会议管理系统 编辑:程序博客网 时间:2024/06/16 07:15

简单介绍并查集:

//这两天复习数据结构,就根据老师的PDF瞎写写^_^

并查集:

并查集是一种树型的数据结构,用于处理一些不相交的集合的合并及查询问题。常常在使用中以森林来表示。集就是让每个元素构成一个单元素的集合,也就是按一定顺序将属于同一组的元素所在的集合合并。
简单来说:
1)并查集是解决动态连通性的一类树形数据结构
2)重点:每个节点只有父亲指针,但压缩树的高度,以实现快速检索树根
3)实现方法:路径压缩按秩合并

1.并查集的路径压缩:

• 在查询时,总是把查询路径上的节点的父亲设为树根

 需要注意的是,如果并查集额外维护了与父亲有关的信息,需要在路径压缩之前对信息进行整合更新

2.并查集的按秩合并:

目的:减少路径压缩时的总压缩量
•理论方法:总是把所有节点高度之和较小的树并入较大的树
•实际方法:把树高较小的树并入较大的树
只有同时采取路径压缩和理论上的按秩合并,才能严格保证并查集的时间复杂度为O(nα(n))
但事实上对于随机情况,只采用路径压缩,复杂度已经能基本达到理论下界。
另外,只采用按秩合并,可以在不破坏树的结构的情况下达到O(nlogn)的时间复杂度。

3.并查集的优缺点:

优点:

• 能够动态维护连通性,且时间复杂度低、常数因子小
• 代码量小、难度低,写起来很方便

缺点:

• 动态程度有限,只能支持Union和Find两种操作
• 动态过程会破坏原有结构,很多信息的维护需要特殊技巧

下面是参考程序0.0:

根据并查集的两个重要操作:
合并两个不相交集合
判断两个元素是否属于同一集合

n是结点数,m是变数,q是询问次数。
#include<iostream>using namespace std;int n,m,q;int father[20001];int findfa(int x)//判断x所属的集合 {int root=x;while(father[root]>=0)//找到最终的根结点 root=father[root];while(root!=x)//压缩路径 {int temp=father[x];father[x]=root;x=temp;}return root;}void Union(int a,int b)//合并两个不同集合的元素 {int temp=father[a]+father[b];if(father[a]>father[b])//较小的树成为较大的数的子树{father[a]=b;father[b]=temp;}else {father[b]=a;father[a]=temp;}}int main(){int a,b;cin>>n>>m>>q;for(int i=1;i<=n;i++)//初始化 father[i]=-1;//各结点的父节点均为-1 for(int i=1;i<m;i++){cin>>a>>b;if(findfa(a)!=findfa(b))Union(a,b);//连通}for(int i=1;i<=q;i++){cin>>a>>b;if(findfa(a)==findfa(b))cout<<"YES"<<endl;else cout<<"NO"<<endl;}return 0;}

原创粉丝点击