并查集的基本操作

点击查看代码
#include<cstdio>
#pragma warning(disable:4996)

//并查集的基本操作
const int maxn = 1001; //最多1000个元素
int n; //并查集元素个数
int father[maxn]; //存储并查集元素

//查找元素x所在集合的根结点
int findFather(int x) {	
	while (x != father[x]) { //如果x不是根结点,则继续向根结点方向查找
		x = father[x]; //将x的父结点作为下一轮的查找结点
	}
}

/*优化后的查找函数(非递归版本)
(1)按照优化前的查找函数方法,获得元素x的根结点r
(2)从元素x出发,重新走一遍查找根结点的路径,将路径上经过的所有结点的父结点都改为根结点r */
int findFatherOptimize(int x) {
	int temp = x; //先存储x的副本,在下面的while中会修改x
	//步骤1,查找元素x的根结点,while循环结束后,x存储的是根结点
	while (x != father[x]) { //只要x不是根结点,就继续回溯父结点
		x = father[x];
	}
	//步骤2,重走一次元素x(即temp)查找根结点的路径,将路径上所有结点的父结点都设为根结点
	while (temp != father[temp]) { //只要temp不是根结点,就继续回溯父结点
		int z = temp; //先存储temp的副本,因为temp在下面会被修改
		temp = father[temp]; //将temp的父结点赋给temp,准备下一轮查找
		father[z] = x; //将temp的父结点改为根结点x
	}
	return x; //返回根结点
}

//优化后的查找函数(递归版本)
int findFatherRecursion(int x) {
	if (x == father[x]) return x; //返回根结点x
	else {
		int root = findFatherRecursion(father[x]); //递归查找根结点root
		father[x] = root; //将查找路径上的所有结点的父结点都设为根结点
		return root; //返回根结点
	}
}

//合并元素a和元素b的两个集合
void Union(int a, int b) { 
	int faA = findFather(a); //查找a所在集合的根结点,存入faA中
	int faB = findFather(b); //查找b所在集合的根结点,存入faB中
	//两个元素不在同一个集合时才进行合并,因此并查集产生的每一个集合都是一棵树,不会出现环
	if (faA != faB) { 
		father[faA] = faB; //将faA的父结点设置为faB,合并两个集合
	}
}


int main() {	
	//并查集初始化
	for (int i = 1; i <= n; i++) { 
		father[i] = i; //每个元素的父结点为自己,每个元素都是根结点
	}

	return 0;
}

posted @ 2022-09-29 21:21  zhaoo_o  阅读(12)  评论(0编辑  收藏  举报