You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
130 lines
4.7 KiB
130 lines
4.7 KiB
/**************************************************************************** |
|
* VCGLib o o * |
|
* Visual and Computer Graphics Library o o * |
|
* _ O _ * |
|
* Copyright(C) 2004-2016 \/)\/ * |
|
* Visual Computing Lab /\/| * |
|
* ISTI - Italian National Research Council | * |
|
* \ * |
|
* All rights reserved. * |
|
* * |
|
* This program is free software; you can redistribute it and/or modify * |
|
* it under the terms of the GNU General Public License as published by * |
|
* the Free Software Foundation; either version 2 of the License, or * |
|
* (at your option) any later version. * |
|
* * |
|
* This program is distributed in the hope that it will be useful, * |
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of * |
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * |
|
* GNU General Public License (http://www.gnu.org/licenses/gpl.txt) * |
|
* for more details. * |
|
* * |
|
****************************************************************************/ |
|
|
|
#ifndef VCG_MATH_UNIONSET_H |
|
#define VCG_MATH_UNIONSET_H |
|
|
|
#include <unordered_map> |
|
#include <vector> |
|
#include <assert.h> |
|
|
|
namespace vcg |
|
{ |
|
/*! |
|
* Given a set of elements, it is often useful to break them up or partition them into a number of separate, nonoverlapping groups. |
|
* A disjoint-set data structure is a data structure that keeps track of such a partitioning. See |
|
* <a href="http://en.wikipedia.org/wiki/Disjoint-set_data_structure">Diskoint-set data structure on Wikipedia </a> for more details. |
|
*/ |
|
template<class OBJECT_TYPE> |
|
class DisjointSet |
|
{ |
|
/************************************************* |
|
* Inner class definitions |
|
**************************************************/ |
|
struct DisjointSetNode |
|
{ |
|
DisjointSetNode(OBJECT_TYPE *x) {obj=x; parent=obj; rank=0;} |
|
OBJECT_TYPE *obj; |
|
OBJECT_TYPE *parent; |
|
int rank; |
|
}; |
|
|
|
typedef OBJECT_TYPE* ObjectPointer; |
|
typedef std::pair< ObjectPointer, int > hPair; |
|
|
|
struct SimpleObjHashFunc{ |
|
inline size_t operator ()(const ObjectPointer &p) const {return size_t(p);} |
|
}; |
|
|
|
std::unordered_map< OBJECT_TYPE*, int > inserted_objects; |
|
typedef typename std::unordered_map< OBJECT_TYPE*, int >::iterator hIterator; |
|
|
|
typedef std::pair< hIterator, bool > hInsertResult; |
|
|
|
|
|
public: |
|
/*! |
|
* Default constructor |
|
*/ |
|
DisjointSet() {} |
|
|
|
/*! |
|
* Makes a group containing only a given element (a singleton). |
|
*/ |
|
void MakeSet(OBJECT_TYPE *x) |
|
{ |
|
int object_count = int(inserted_objects.size()); |
|
assert(inserted_objects.find(x)==inserted_objects.end()); //the map mustn't already contain the object x |
|
nodes.push_back(DisjointSetNode(x)); |
|
inserted_objects.insert( hPair(x,object_count) ); |
|
} |
|
|
|
/*! |
|
* Combine or merge two groups into a single group. |
|
*/ |
|
void Union(OBJECT_TYPE *x, OBJECT_TYPE *y) |
|
{ |
|
OBJECT_TYPE *s0 = FindSet(x); |
|
OBJECT_TYPE *s1 = FindSet(y); |
|
Link(s0, s1); |
|
} |
|
|
|
/*! |
|
* Determine which group a particular element is in. |
|
*/ |
|
OBJECT_TYPE* FindSet(OBJECT_TYPE *x) |
|
{ |
|
hIterator pos = inserted_objects.find(x); |
|
assert(pos!=inserted_objects.end()); |
|
DisjointSetNode *node = &nodes[pos->second]; |
|
if (node->parent!=x) |
|
node->parent = FindSet(node->parent); |
|
return node->parent; |
|
} |
|
|
|
private: |
|
/* |
|
*/ |
|
void Link(OBJECT_TYPE *x, OBJECT_TYPE *y) |
|
{ |
|
hIterator xPos = inserted_objects.find(x); |
|
hIterator yPos = inserted_objects.find(y); |
|
assert(xPos!=inserted_objects.end() && yPos!=inserted_objects.end()); |
|
DisjointSetNode *xNode = &nodes[xPos->second]; |
|
DisjointSetNode *yNode = &nodes[yPos->second]; |
|
if (xNode->rank>yNode->rank) |
|
xNode->parent = y; |
|
else |
|
{ |
|
yNode->parent = x; |
|
if (xNode->rank==yNode->rank) |
|
yNode->rank++; |
|
} |
|
} |
|
|
|
protected: |
|
std::vector< DisjointSetNode > nodes; |
|
}; |
|
};// end of namespace vcg |
|
|
|
#endif //VCG_MATH_UNIONSET_H
|
|
|