Fortune-ley dejó base class5- tema 6-disjuntos conjunto para lograr

1. Introducción: disjuntos-set

Y el papel de la investigación hay dos conjuntos principales:
① rápida comprobar dos elementos son el mismo conjunto
② de combinación de dos conjuntos.

estructura (1) disjunta-set

Cuando la colección es sólo un elemento, que representa el conjunto de nodos del elemento que es, el padre de los elementos es el suyo.
Aquí Insertar imagen Descripción
Cuando hay más de un conjunto de nodos, el padre del nodo inferior al nodo superior, el padre más superior nodos apuntan a sí mismos, esto se llama el nodo de nivel superior representa el conjunto de nodos. Figura padre como 5,4 a 3,3 padre es su propio.
Aquí Insertar imagen Descripción

(2) y controlar el conjunto de principios

① Encontrar: Supongamos hallazgo a, b están en el mismo conjunto, para a, b encontrar su nodo representativo, el nodo representante si no son diferentes en el mismo conjunto, la misma que en el mismo conjunto. A continuación, no en el mismo conjunto de 2,5, 4,5 mismo conjunto
Aquí Insertar imagen Descripción
② combinado
en el caso en que dos conjuntos no son el mismo conjunto, el representante de conjunto de nodos padre de longitud más corta se refiere a la longitud del nodo representativo.

Aquí Insertar imagen Descripción

2. Análisis

(1) Diseño de la clase

El uso de dos disjuntos mapa-conjunto dado cuenta por primera fatherMap encontrar su elemento padre, clave representa el nodo actual, el valor de su nodo padre. SizeMap utiliza para registrar el segundo conjunto de su longitud total, clave indica el nodo actual, el valor es la longitud de la recogida.

class UnionFindSet 
{
private:
	hash_map<char,char> fatherMap;
	hash_map<char,int> sizeMap;
public:
	 UnionFindSet(vector<char> data);//构造
	 char findHead(char cur);		//找集合的代表节点
	 bool isameset(char a,char b);	//判断是否是同一个集合
	 void Union(char a,char b);		//合并集合
};

constructor

UnionFindSet::UnionFindSet(vector<char> data)
{
	{
		 fatherMap.clear();
		 sizeMap.clear();
		 //将vector的元素各自形成一个集合
		 for(auto var:data)
		 {
			 fatherMap.insert(pair<char,char>(var,var));//单个节点father指向自己
			 //sizeMap[var] = 1;
			 sizeMap.insert(pair<char,int>(var,1));//单个节点长度是1
		 }
	 }
}

(2) Busca un nodo representante

Características nodo representativo es su propio nodo padre, la idea es el nodo actual a su nodo padre es el mismo nodo por fatherMap vino en nombre de un paso a paso a través.

//递归版
char UnionFindSet::findHead(char cur)
{
	char father = fatherMap[cur];	//找到当前节点的father
	if(father != cur)				//father和当前节点不同表示当前节点不是代表节点,继续找
	{
		cur = father;
		father = findHead(cur);		//递归放入father继续找
	}
	fatherMap[cur] = father;		//递归后father是代表节点,对每个子节点father节点都改为代表节点
	return father;
}
//非递归版
char UnionFindSet::findHead(char cur)
{
	stack<char> child;
	while(fatherMap[cur] != cur)
	{
		child.push(cur);		//将沿途非代表节点入栈
		cur = fatherMap[cur];	//将当前节点father变为当前节点继续判断
	}
	//运行至此处时,cur是代表节点
	while(!child.empty())
	{
		fatherMap[child.top()] = cur;	//将栈中的非代表节点的father指向代表节点,完成扁平化
		child.pop();					//出栈
	}
	return cur;
}

(3) determinar si el mismo conjunto

bool UnionFindSet::isameset(char a,char b)
{
	return findHead(a) == findHead(b);
}

(4) dos conjuntos combinados

En el caso en que dos nodos representante diferente, incluso una longitud conjunto comparación de nodos representa un punto de recogida a una larga serie de corto, entonces la longitud total de los dos conjuntos se aplica al nodo representativo.
Nota: No hay sentido de la longitud del nodo no primario, al comparar comparar solamente representa la longitud total del nodo.

void UnionFindSet::Union(char a,char b)
{
	//找出两个集合的代表节点
	char head1 = findHead(a);
	char head2 = findHead(b);

	if(head1 == NULL || head2 == NULL)//边界问题,空集合直接返回
		return;

	if(head1!=head2)				//不在同一集合时合并
	{
		//记录两个代表节点的长度
		int size1 = sizeMap[head1];
		int size2 = sizeMap[head2];
		//将短的接入长的中
		if(size1 <= size2)
		{
			fatherMap[head1] = head2;
			sizeMap[head2] = size1 + size2;
		}
		else
		{
			fatherMap[head2] = head1;
			sizeMap[head1] = size1 + size2;
		}
	}
}

3. El código completo

#include<iostream>
#include<hash_map>
#include<vector>
#include<stack>
using namespace std;

class UnionFindSet 
{
private:
	hash_map<char,char> fatherMap;
	hash_map<char,int> sizeMap;
public:
	 UnionFindSet(vector<char> data);//构造
	 char findHead(char cur);		//找集合的代表节点
	 bool isameset(char a,char b);	//判断是否是同一个集合
	 void Union(char a,char b);		//合并集合
};

UnionFindSet::UnionFindSet(vector<char> data)
{
	{
		 fatherMap.clear();
		 sizeMap.clear();
		 //将vector的元素各自形成一个集合
		 for(auto var:data)
		 {
			 fatherMap.insert(pair<char,char>(var,var));//单个father指向自己
			 //sizeMap[var] = 1;
			 sizeMap.insert(pair<char,int>(var,1));//单个长度是1
		 }
	 }
}
//递归版
//char UnionFindSet::findHead(char cur)
//{
//	char father = fatherMap[cur];	//找到当前节点的father
//	if(father != cur)				//father和当前节点不同表示当前节点不是代表节点,继续找
//	{
//		cur = father;
//		father = findHead(cur);		//递归放入father继续找
//	}
//	fatherMap[cur] = father;		//递归后father是代表节点,对每个子节点father节点都改为代表节点
//	return father;
//}


//非递归版
char UnionFindSet::findHead(char cur)
{
	stack<char> child;
	while(fatherMap[cur] != cur)
	{
		child.push(cur);		//将沿途非代表节点入栈
		cur = fatherMap[cur];	//将当前节点father变为当前节点继续判断
	}
	//运行至此处时,cur是代表节点
	while(!child.empty())
	{
		fatherMap[child.top()] = cur;	//将栈中的非代表节点的father指向代表节点,完成扁平化
		child.pop();					//出栈
	}
	return cur;
}

bool UnionFindSet::isameset(char a,char b)
{
	return findHead(a) == findHead(b);
}

void UnionFindSet::Union(char a,char b)
{
	//找出两个集合的代表节点
	char head1 = findHead(a);
	char head2 = findHead(b);

	if(head1 == NULL || head2 == NULL)//边界问题,空集合直接返回
		return;

	if(head1!=head2)				//不在同一集合时合并
	{
		//记录两个代表节点的长度
		int size1 = sizeMap[head1];
		int size2 = sizeMap[head2];
		//将短的接入长的中
		if(size1 <= size2)
		{
			fatherMap[head1] = head2;
			sizeMap[head2] = size1 + size2;
		}
		else
		{
			fatherMap[head2] = head1;
			sizeMap[head1] = size1 + size2;
		}
	}
}
int main()
{
	vector<char> temp;//={'A','B','C','D','E,'F'};
	temp.push_back('A');
	temp.push_back('B');
	temp.push_back('C');
	temp.push_back('D');
	temp.push_back('E');
	temp.push_back('F');
	temp.push_back('G');
	temp.push_back('H');
	UnionFindSet m(temp);
	m.Union('B','A');
	
	m.Union('C','B');

	m.Union('D','E');
	m.Union('B','D');
	system("pause");
	return 0;
}

4. Resultados Run

El conjunto B y el conjunto de D se combinaron, los resultados se muestran a continuación A, B, C, E al punto A, D al punto E.
Aquí Insertar imagen Descripción
Aquí Insertar imagen Descripción

Publicado 51 artículos originales · ganado elogios 1 · vistas 1368

Supongo que te gusta

Origin blog.csdn.net/shi_xiao_xuan/article/details/104144598
Recomendado
Clasificación