并查集总结

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<<"请输入节点个数"<>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<

3.优化操作:

3.1按秩合并:

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

3.2路径压缩:

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


你可能感兴趣的:(算法精讲,数据结构,算法与数据结构)