并查集总结

原创 2016年08月29日 10:06:27

1.并查集:

什么是并查集,我们将并查集称之为不相交集合,在处理例如查找几个元素是否属于相同的集合的时候我们使用并查集可以达到非常高的处理速度(在合并和查找方面),我们利用并查集的思想有一点很重要就是我们我们利用的森林(父亲表示树)来对不同的不相交集合的状态,我们利用每个集合的根作为代表元素来对整个集合的数据进行“牵一发动全身”的合并处理

这里我们的额=编号和处理对都是整数,但是如果我们如果要对字符串等进行并查集的操纵,我们可以利用哈希函数进行映射,转化成相应的整数进行操作

3.1数据结构的选择

在这里,我们事先的时候通常用的是父亲表示树,我们的节点域的内容是父亲的标号,因为我们在进行相应的操作的时候没有必要对子节点进行查询,但是我们需要不断对父亲的位置进行查询,所以说我们选用父亲表示树构成的森林

2.具体操作:

对于并查集我们有如下几个特殊的操作
1.init()初始化操作,我们构建一群根为自己的森林
2.find()查找操作,我们find函数返回该元素对应的集合的根节点的编号(本集合的编号)
3.unit()合并操作,我们将两个元素对应的集合进行合并,如果是同一集合我们不进行操作,否则我们队两颗树进行合并
4.same()判断根节点是否相同的操纵
5.count()技术操纵,记录该森林中的数的个数(对应的不相交集合的个数)

先上代码:
#include"iostream"
#include"cstdio"
#include"cstring"
#include"cstdlib"
#define N 10000

using namespace std;

class uniontree
{
	public:
		uniontree()
		{
			memset(fa,0,sizeof(fa));
			memset(deep,0,sizeof(deep));
			num=0;
		}
		void init()   //初始化操作 
		{
			for(int i=1;i<=n;i++)
			{
				fa[i]=i;
				deep[i]=1;
			} 
			num=n;   //初始化我们的不相交集合的数目就是元素的个数 
		}
		int find(int x)   //查找操作 
		{
			if(x==fa[x]) return x;   //如果该节点的父亲就是自己,那我们认为我们找到了该节点对应的集合的根(就是其本身)
			else return fa[x]=find(fa[x]);   //这里我们用到了路径压缩的策略,每次我们进行查找的时候,我们都将集合的路径整体进行压缩,该路径的元素全部直接指向该集合的根节点 
		}
		void unit(int x,int y)   //合并操作
		{
			x=find(x);   //路径压缩的同时查找根 
			y=find(y);
			if(x==y) return ;
			else
			{
				if(deep[x]>deep[y]) fa[y]=x;
				else
				{
					fa[x]=y;
					if(deep[x]==deep[y]) deep[y]++; 
				} 
				num--;   //每次成功合并一次,集合个数递减 
			} 
		} 
		bool same(int x,int y)   //判断集合是否相同 
		{
			return find(x)==find(y);
		}
		int count()
		{
			return num;
		} 
		friend istream& operator>>(istream& in,uniontree& k)
		{
			cout<<"请输入节点个数"<<endl;cin>>k.n;
			return in;
		}
	private:
		int num;  //记录森林中的不相交集合的数目
		int fa[N];     //父亲域 
		int deep[N];   //按秩进行合并的优化,之后我们会讲到 
		int n;   //初始的元素的个数 
};

int main()
{
	uniontree lantian,liutianqi; 
	cin>>lantian;
	lantian.init();
	cout<<lantian.count()<<endl;
	lantian.unit(2,3);
	cout<<lantian.count()<<endl;
	return 0;
} 

3.优化操作:

3.1按秩合并:

在这里我们的deep代表的是每个集合的秩,首先我们需要明确一点,在我们没有路径压缩的时候,我们森林中的每个集合树的高度都是随机的,并不都是1,所以说,这里会出现我们的集合树退化成偏树的情况,所以说,我们每次都要将树深浅的数插到树深大的树中,因为我们的合并函数中,我们利用了进行了路径压缩的查找函数,但是我们的树深相对大小还是不可预测的,我们这里的时候我们的秩在路径压缩的时候并不改变,所以说我们之后的判断都很复杂,我们在这里我们把秩只是看做一个上届,但是这一点我们已经可以避免我们将集合树退化的情况了

3.2路径压缩:

我们每次查找的时候,我们将亲子直接连接到集合的根上,我们下次再次查找相同的元素的时候,对根的查找可以优化到O(1)复杂度,何乐而不为


版权声明:本文为博主原创文章,未经博主允许不得转载。

从头思考并查集

(学习并查集之前)    LA 3644         题意抽象:有一些线段,按顺序插入这些线段,如果插入一条线段后形成环,则不选择这条线段。求解最后又多少条线段被放弃。         分析:判断...
  • litrain_1
  • litrain_1
  • 2015年04月20日 16:14
  • 142

并查集总结(一)

A Bug's Life Time Limit: 15000/5000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others) ...
  • ACMer_hades
  • ACMer_hades
  • 2015年05月19日 20:01
  • 537

并查集的理解与实现总结

并查集的应用十分广泛,包括一些算法,当应用上并查集的时候,也会更容易实现。下面总结下并查集的相关内容。 什么是并查集? 个人的理解是:并查集就是对集合三种常用操作的再一次抽象。分别是集合的合并(U...
  • weixin_37818081
  • weixin_37818081
  • 2017年11月25日 17:44
  • 84

并查集应用总结

一.并查集的概念 并查集是一种算法可以用来判断相互关联(同属一个集合)的元素属于几个集合,也可以用来判断图结构中的两点是否是联通的。并查集的设计思路是这样的: 在程序执行过程中任意元素一定输于以下...
  • u013555159
  • u013555159
  • 2016年05月06日 21:23
  • 595

oracle数据库将多个列的查询结果集合并到一行中

oracle数据库使用系统函数将多个列的查询结果集合并到一行中。
  • qin904863396
  • qin904863396
  • 2017年01月03日 19:34
  • 6304

MS SQL 合并结果集并求和

业务情景: 有这样一张表: 其中Id列为表主键,Name为用户名,State为记录的状态值,Note为状态的说明,方便阅读。 需求描述:需要查询出这样的结果:某个人某种状态的记录数,如:张三,待审...
  • a497785609
  • a497785609
  • 2015年02月13日 10:59
  • 6214

SqlServer_select-多次sum查询结果合并;

转自  http://blog.csdn.net/cyb_23/article/details/22472669 没事就瞎看看。如果一对多的关系,可以另外的表查询出来的数据作为一个字段。是平时想的...
  • liuqiaoying_lqy
  • liuqiaoying_lqy
  • 2016年06月24日 10:45
  • 3353

并查集总结-------

  • 2009年04月09日 19:30
  • 4KB
  • 下载

并查集代码

  • 2015年12月12日 20:18
  • 1KB
  • 下载

ACM并查集讲解的深化和扩展

  • 2016年07月01日 17:27
  • 1.58MB
  • 下载
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:并查集总结
举报原因:
原因补充:

(最多只允许输入30个字)