並查集(UnionFind)接口封裝:C++實現

接口的主要內容如下:

1、並查集初始化
2、合併:合併兩棵樹
3、查找:找某一節點所在樹的根節點
4、連通性判斷:判斷兩個節點是否連通,實質是判斷其根節點是否相同
5、路徑壓縮:降低樹的高度,進而降低查找的複雜度
6、連通分量個數統計
7、平衡性:使用size統計每棵樹的節點數量,在合併的時候,總是讓重量較小的樹合併到重量較大的樹的下方(即小樹的根節點指向大樹的根節點),避免樹的高度變得不平衡。

#include <vector>
using namespace std;

// 並查集
class UnionFind
{
private:
	int count;			// 並查集中連通分量的個數
	vector<int> size;	// 存儲樹的"重量",用於在兩顆樹合併時,平衡樹的高度
	vector<int> parent; // 存儲節點

public:

	// 並查集初始化,開始時每個節點都是獨立的
	UnionFind(int n)
	{
		this->count = n;
		parent.resize(n);
		size.resize(n);
		for (int i = 0; i < n; ++i)
		{
			parent[i] = i;
			size[i] = 1;
		}
	}

	// 返回當前集合中連通分量的個數
	int count()
	{
		return this->count;
	}

	// 查找某個連通分量的根節點
	int findRoot(int x)
	{
		while (parent[x] != x)
		{
			parent[x] = parent[parent[x]]; // 路徑壓縮
			x = parent[x];
		}
		return x;
	}

	// 判斷兩個分量是否連通
	bool connected(int p, int q)
	{
		int root_p = findRoot(p);
		int root_q = findRoot(q);
		return root_p == root_q;
	}

	// 合併兩個集合
	void UnionSet(int p, int q)
	{
		int root_p = findRoot(p);
		int root_q = findRoot(q);
		if (root_p == root_q) return;
		
		if (size[root_p] > size[root_q])
		{
			parent[root_q] = root_p;
			size[root_p] += size[root_q];
		}
		else
		{
			parent[root_p] = root_q;
			size[root_q] += size[root_p];
		}
		this->count--;
	}
};

謝謝閱讀。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章