算法笔记---并查集

并查集是一种维护集合的数据结构,它的名字中“并”“查”“集”分别取自Union(合并)、Find(查找)、Set(集合)这3个单词。也就是说,并查集支持下面两个操作:

①合并:合并两个集合。
②查找:判断两个元素是否在一个集合。

那么并查集是用什么实现的呢?
其实就是用一个数组:

int father[N]

其中fahter[i]表示元素i的父亲结点,而父亲结点本身也是这个集合内的元素(1≤i≤N)。例如father[1]=2就表示元素1的父亲结点是元素2,以这种父系关系来表示元素所属的集合。另外,如果father[i]=i,则说明元素i是该集合的根结点,但对同一个集合来说只存在一个根结点,且将其作为所属集合的标识。

#include<iostream>
using namespace std;

const int max_union_find_set = 1001;
int father[max_union_find_set] = { 0 };

//初始化
void init(int father[]) {
	for (int i = 1;i <= max_union_find_set;i++)
	{
		father[i] = i;
	}
}

//查找(递归)
int find_father(int x) {
	if (father[x] == x)
	{
		return x;
	}
	else
	{
		return find_father(father[x]);
	}
}

//合并
void union_father(int a, int b) {
	int father_a = find_father(a);
	int father_b = find_father(b);
	if (father_a != father_b)//如果不在一个集合,则合并
	{
		father[father_a] = father_b;
	}
}

int main() {

	
	system("pause");
	return 0;
}

在合并的过程中,只对两个不同的集合进行合并,如果两个元素在相同的集合中,那么就不会对它们进行操作。这就保证了在同一个集合中一定不会产生环,即并查集产生的每一个集合都是一棵树。

上面讲解的并查集查找函数是没有经过优化的,在极端情况下效率较低。现在来考虑一种情况,即题目给出的元素数量很多并且形成一条链,那么这个查找函数的效率就会非常低。

下面给出解决方案:路径优化
这相当于把查找结点的路径上的所有结点的父亲都指向根结点
则查找的复杂度可以变为O(1)。

int find_father(int x) {
	if (father[x] == x)
	{
		return x;
	}
	else
	{
		int root_val = find_father_2(father[x]);
		father[x] = root_val;//将根结点赋值给father[x]
		return root_val;//返回根结点
	}
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章