并查集(c++)

并查集简介:在一些应用问题中,需要将n个不同的元素划分为一组不相交的集合,在划分过程中需要反复查询某个元素归属于哪个集合。并查集就是一种适合于描述这类问题的抽象数据类型。

并查集主要支持的操作

  1. merge(Root1, Root2) //并操作;
  2. get (x) //搜索操作;
  3. UFS (s) //构造函数。

一般情形,并查集主要涉及两种数据类型:集合名类型和集合元素的类型。

在许多情况下,可以用整数作为集合名。如果集合中有n个元素,可以用1到n之间的整数表示集合元素。

对于并查集来说,每个集合用一棵树表示。

集合中每个元素的元素名分别存放在树的结点中,此外,树的每一个结点还有一个指向其双亲结点的指针。

根结点的父指针为负数,其绝对值表示集合中的元素个数。

// 并查集.cpp : 此文件包含 "main" 函数。程序执行将在此处开始并结束。
//并查集的基本操作

#include "pch.h"
#include 
#include
using namespace std;
const int defaultSize = 10;

class UFS {
private:
	vector parent;
public:
	UFS(int size = defaultSize) {
		//初始化:初始的时候每个结点各自为一个集合,
		//parent[i]表示结点 i 的父亲结点,如果 parent[i]=i,我们认为这个结点是当前集合根结点。
		for (int i = 0; i < size; i++)
		{
			parent.push_back(i);
		}
	}
	int old_get(int x)//查找:查找结点所在集合的根结点,结点 x 的根结点必然也是其父亲结点的根结点。
	{
		while (parent[x]!=x)
		{
			x = parent[x];
		}
		return x;
	}
	void merge(int x, int y)//将两个节点所在的集合并起来,一般要首先检查两个节点是否属于同一个集合
	{
		x = old_get(x);
		y = old_get(y);
		if (x != y)// 不在同一个集合
		{
			parent[y] = x;
		}
	}
	/*
	前面的并查集的复杂度实际上在有些极端情况会很慢.
	比如树的结构正好是一条链,那么最坏情况下,每次查询的复杂度达到了O(n)。
	这并不是我们期望的结果。路径压缩的思想是,我们只关心每个结点的父结点,而并不太关心树的真正的结构。
	这样我们在一次查询的时候,
	可以把查询路径上的所有结点的father[i]都赋值成为根结点。
	只需要在我们之前的查询函数上面进行很小的改动
	*/
	int get(int x)
	{
		if (parent[x] == x)
			return x;
		else
			return parent[x] = get(parent[x]);
	}
	/*
	路径压缩在实际应用中效率很高,
	其一次查询复杂度平摊下来可以认为是一个常数。并且在实际应用中,我们基本都用带路径压缩的并查集。
	*/
	
	};
class WUFS {
	/*
	所谓带权并查集,是指结点存有权值信息的并查集。并查集以森林的形式存在,
	而结点的权值,大多是记录该结点与祖先关系的信息。比如权值可以记录该结点到根节点的距离。
	*/
	/*
	例题
	在排队过程中,初始时,一人一列。一共有如下两种操作。
	合并:令其中的两个队列 A,B 合并,也就是将队列 A 排在队列 B 的后面。
	查询:询问某个人在其所在队列中排在第几位。
	*/
	/*
	我们不妨设 size[]为集合中的元素个数,dist[]为元素到队首的距离,
	*/
private:
	vector parent;
	vector size;
	vector dis;
public:
	WUFS(int s)
	{
		for (int i = 0; i < s; i++)
		{
			parent.push_back(i);
			dis.push_back(0);
			size.push_back(1);
		}
	}
	int get(int x)
	{
		if (parent[x] == x)
			return x;
		int y = parent[x];
		parent[x] = get(y);//太巧妙了
		dis[x] += dis[y];
		return parent[x];
	}
	void merge(int x, int y)
	{
		x = get(x);
		y = get(y);
		if (x != y)
		{
			parent[x] = y;
			dis[x] = size[y];
			size[y] += size[x];
		}
	}
};
int main()
{
    std::cout << "Hello World!\n"; 
}

你可能感兴趣的:(data,structure)