【数据结构】并查集Union类的实现和优化

并查集这种数据结构使用数组实现 虽然是树形结构 但是是数组实现
原始形式
每一个元素都有自己id值 如果id值一样 就是一组元素
合并时 遍历每一个元素 更改其id值

#pragma once
#include <iostream>
#include<cassert>
using namespace std;
//没个元素都有自己id值 如果id值一样 就是一组元素
//合并时 遍历没个元素 更改其id值
class UnionFind1
{
private:
	int* parent;
	int count;
public:
	UnionFind1(int n)
	{
		count = n;
		parent = new int[n];
		for (int i = 0;i < n;i++)
		{
			parent[i] = i;
		}
	}
	~UnionFind1()
	{
		delete[] parent;
		count = 0;
	}
	int find(int p)
	{
		assert(p >= 0 && p < count);
		return parent[p];
	}
	bool isConnected(int p, int q)
	{
		return find(p) == find(q);
	}
	void unionElements(int p, int q)
	{
		int pparent = find(p);
		int qparent = find(q);
		if(find(p)==find(q))
		{
			return;
		}
		for (int i = 0;i < count;i++)
		{
			
			if (parent[i] == pparent)
			{
				parent[i] = qparent;
			}
		}
	}

};

使用类似链表的形式 把值设置成其父节点的值

#pragma once
#include <iostream>
#include<cassert>
using namespace std;
//将储存节点的父节点的值 可能会造成查找很慢
class UnionFind2
{
private:
	int* parent;
	int count;
public:
	UnionFind2(int n)
	{
		parent = new int[n];
		count = n;
		for (int i = 0;i < n;i++)
		{
			parent[i] = i;
		}

	}
	~UnionFind2()
	{
		count = 0;
		delete[] parent;
	}
	int find(int p)
	{
		assert(p >= 0 && p < count);
		while (parent[p] != p)
		{
			p = parent[p];
		}
		return p;
	}
	bool isConnected(int p, int q)
	{
		return find(p) == find(q);
	}
	void unionElements(int p, int q)
	{
		int proot = find(p);
		int qroot = find(q);//尽量少调用函数 将返回值赋给变量
		if (proot == qroot)return;
		parent[proot] = qroot;//根节点连接另一个根节点
	}
};

将子树少的节点指向子树多的节点

#pragma once
#include <iostream>
#include<cassert>
using namespace std;
class UnionFind4
{
private:
private:
	int* parent;
	int count;
	int* sz;
public:
	UnionFind4(int n)
	{
		parent = new int[n];
		sz = new int[n];
		count = n;
		for (int i = 0;i < n;i++)
		{
			parent[i] = i;
			sz[i] = 1;
		}

	}
	~UnionFind4()
	{
		count = 0;
		delete[] parent;
		delete[] sz;
	}
	int find(int p)
	{
		assert(p >= 0 && p < count);
		while (p != parent[p])
		{
			p = parent[p];
		}
		return p;
	}
	int isConnected(int p, int q)
	{
		return find(p) == find(q);
	}
	void unionElements(int p, int q)
	{
		int pRoot = find(p);
		int qRoot = find(q);
		if (pRoot == qRoot)
		{
			return;
		}
		if (sz[pRoot] > sz[qRoot])
		{
			parent[qRoot] = pRoot;
			sz[pRoot] += sz[qRoot];


		}
		else
		{
			parent[pRoot] = qRoot;
			sz[qRoot] += sz[pRoot];
		}
	}
};

将层数少的节点指向层数多的节点 维护rank

#pragma once
#include <iostream>
#include<cassert>
using namespace std;
class UnionFind3
{
private:
	int* parent;
	int count;
	int* rank;
public:
	UnionFind3(int n)
	{
		parent = new int[n];
		rank = new int[n];
		count = n;
		for (int i = 0;i < n;i++)
		{
			parent[i] = i;
			rank[i] = 1;
		}

	}
	~UnionFind3()
	{
		count = 0;
		delete[] parent;
		delete[] rank;
	}
	int find(int p)
	{
		assert(p >= 0 && p < count);
		while (p != parent[p])
		{
			p = parent[p];
		}
		return p;
	}
	int isConnected(int p, int q)
	{
		return find(p) == find(q);
	}
	void unionElements(int p, int q)
	{
		int pRoot = find(p);
		int qRoot = find(q);
		if (pRoot == qRoot)
		{
			return;
		}
		if (rank[pRoot] > rank[qRoot])
		{
			parent[qRoot] = pRoot;

		}
		else if (rank[pRoot] < rank[qRoot])
		{
			parent[pRoot] = qRoot;
		}
		else
		{
			parent[pRoot] = qRoot;
			rank[qRoot]+=1;
		}
	}
};

查找的优化 链式查找
两种优化方法 第一种 将当前节点的父节点改成父亲的父亲
第二种 使子节点直接指向根节点(由于使用了递归 所以实现效率还没有第一种高 和理论想法不符)

#pragma once
#include <iostream>
#include<cassert>
using namespace std;
class UnionFind5
{
private:
	int count;
	int* rank;
	int* parent;
public:
	UnionFind5(int n)
	{
		parent = new int[n];
		rank = new int[n];
		count = n;
		for (int i = 0;i < n;i++)
		{
			parent[i] = i;
			rank[i] = 1;
		}

	}
	~UnionFind5()
	{
		count = 0;
		delete[] parent;
		delete[] rank;
	}
	int find(int p)
	{
		assert(p >= 0 && p < count);
		while (p != parent[p])
		{
			parent[p] = parent[parent[p]];
			p = parent[p];
		}
		//方法2 递归调用 在find的过程中 递归地将没给元素指向根节点
		while (p != parent[p])
		{
			parent[p] = find(parent[p]);
		}
		return p;
	}
	int isConnected(int p, int q)
	{
		return find(p) == find(q);
	}
	void unionElements(int p, int q)
	{
		int pRoot = find(p);
		int qRoot = find(q);
		if (pRoot == qRoot)
		{
			return;
		}
		if (rank[pRoot] > rank[qRoot])
		{
			parent[qRoot] = pRoot;

		}
		else if (rank[pRoot] < rank[qRoot])
		{
			parent[pRoot] = qRoot;
		}
		else
		{
			parent[pRoot] = qRoot;
			rank[qRoot] += 1;//教程中没有提及rank的维护
		}
	}
};
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值