【第22期】观点:IT 行业加班,到底有没有价值?

并查集总结

原创 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)复杂度,何乐而不为


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

相关文章推荐

并查集总结

并查集总结

并查集简单总结

并查集
  • ifeli
  • ifeli
  • 2017-07-07 10:18
  • 83

并查集详解 ——图文解说,简单易懂(转)

并查集是我暑假从高手那里学到的一招,觉得真是太精妙的设计了。以前我无法解决的一类问题竟然可以用如此简单高效的方法搞定。不分享出来真是对不起party了。(party:我靠,关我嘛事啊?我跟你很熟么?)...

并查集 小结

并查集在许多题目里其实只是用来辅助的一个小数据结构,用来实现简单的查找和合并。本文只挑选了以并查集为中心、以并查集的灵活运用为根本的题目——经典的&&特殊的技巧[BZOJ4195][Noi2015]程...

并查集总结(一)

A Bug's Life Time Limit: 15000/5000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others) ...

并查集总结

并查集详解 - ACM并查集算法 - 并查级特点 并查集总结总结两点就是“并”和“查”。何谓“并查集”定义并查集是一种树型的数据结构,用于处理一些不相交集合(Disjoint Sets)的合并及查询问...

并查集总结

并查集是我暑假从高手那里学到的一招,觉得真是太精妙的设计了。以前我无法解决的一类问题竟然可以用如此简单高效的方法搞定。不分享出来真是对不起party了。(party:我靠,关我嘛事啊?我跟你很熟么?)...

【转载】并查集总结

http://ahxgw.tk/archives/disjoint-sets 加上汪维正的 亲戚关系 团伙 http://hi.baidu.com/wwzwdwd/blog/ite...

并查集专题【完结】

并查集专题整理

算法题<度度熊就是要刷排名第一>

程序: /** * 度度熊就是要刷排名第一 */ #include #include #include #include #include using namespace std; ...
收藏助手
不良信息举报
您举报文章:深度学习:神经网络中的前向传播和反向传播算法推导
举报原因:
原因补充:

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