并查集---------2021年12月15日

并查集

在这里插入图片描述 实现两个集合合并,并且好找父节点
这里设计一个方法,那其中一个根结点作为另一个树的子结点
在这里插入图片描述

操作总结:

在这里插入图片描述
初始化
初始化并查集
这里把所有结点的父节点都为-1 ,
父节点用数组值表示,子节点用下标表示


UFSets::UFSets(int sz) {
	size = sz;
	parent = new int[size];                //创建双亲数组
	for (int i = 0; i < size; i++) {
		parent[i] = -1;
	 }
}

这里找父节点

在这里插入图片描述

返回下标就是根,因为根就没有父亲了,值为-1


//函数搜索并返回包含元素x的树的根。

int UFSets::Find(int x) {
	while (parent[x] >= 0) {
		x = parent[x];
	}
	return x;  //返回下标就是根,因为根就没有父亲了,值为-1
}

找到树根之后,进行合并操作

在这里插入图片描述

#ifndef UFsets_h
#define UFsets_h
#include <iostream>
#include <string>
#include <iomanip>
using namespace std;
const int DefaultSize1 = 30;

//集合中的各个子集合互不相交
class UFSets {
public:
	UFSets(int sz = DefaultSize1);
	UFSets(UFSets& R);
	~UFSets() {
		delete[]parent;
	}
	UFSets& operator = (UFSets& R);		//操作符重载,实现集合赋值
	void SimpleUnion(int Root1, int Root2);//子集合并
	int Find(int x);					//查找x的根
	void WeightedUnion(int Root1, int Root2);//压缩高度的合并算法
	int CollapsingFind(int i);			//使用折叠规则的搜索算法
	void output(ostream& out = cout);
	friend ostream& operator << (ostream& out, UFSets& R) {
		int i;
		out << "\n" << string(70, '=');
		for (int j = 0; j <= (R.size - 1) / 10; j++) {
			out << "\nNode:\t";
			for (i = 10 * j; i < 10 * (j + 1) && i < R.size; i++) {
				out << setw(6) << i;
			}
			cout << "\nParent:\t";
			for (i = 10 * j; i < 10 * (j + 1) && i < R.size; i++) {
				out << setw(6) << R.parent[i];
			}
			if (i < R.size) {
				out << "\n" << string(70, '-');
			}
		}
		out << "\n" << string(70, '=') << "\n";
		return out;
	}
private:
	int* parent;						//集合元素数组(双亲表示)
	int size;							//集合元素的数目
};
#endif 
/* UFSets_h */

//初始化并查集
//这里把所有结点的父节点都为-1 ,
//父节点用数组值表示,子节点用下标表示
UFSets::UFSets(int sz) {
	size = sz;
	parent = new int[size];                //创建双亲数组
	for (int i = 0; i < size; i++) {
		parent[i] = -1;
	}
}

UFSets::UFSets(UFSets& R) {
	size = R.size;
	parent = new int[size];
	for (int i = 0; i < size; i++) {
		parent[i] = R.parent[i];
	}
}

UFSets& UFSets::operator = (UFSets& R) {
	size = R.size;
	parent = new int[size];
	for (int i = 0; i < size; i++) {
		parent[i] = R.parent[i];
	}
	return *this;
}

//函数搜索并返回包含元素x的树的根。
int UFSets::Find(int x) {
	while (parent[x] >= 0) {
		x = parent[x];
	}
	return x;  //返回下标就是子孩子
}

//求两个不相交集合Root1与Root2的并(将Root2连接到Root1下面)
void UFSets::SimpleUnion(int Root1, int Root2) {
	int r1 = Find(Root1), r2 = Find(Root2);
	if (r1 != r2) //两个树根不同
	{
		/*
		parent[r1] += parent[r2];
		parent[r2] = r1;
		*/
		parent[r1] = r2;
	}
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值