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.
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.
(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
② 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.
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.