removed old style usage of hash map and substituted with c+11 sytle unordered set and map.
This commit is contained in:
parent
ad95129d02
commit
47aaea332a
|
@ -8,7 +8,7 @@
|
||||||
* \ *
|
* \ *
|
||||||
* All rights reserved. *
|
* All rights reserved. *
|
||||||
* *
|
* *
|
||||||
* This program is free software; you can redistribute it and/or modify *
|
* 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 *
|
* it under the terms of the GNU General Public License as published by *
|
||||||
* the Free Software Foundation; either version 2 of the License, or *
|
* the Free Software Foundation; either version 2 of the License, or *
|
||||||
* (at your option) any later version. *
|
* (at your option) any later version. *
|
||||||
|
@ -24,143 +24,107 @@
|
||||||
#ifndef VCG_MATH_UNIONSET_H
|
#ifndef VCG_MATH_UNIONSET_H
|
||||||
#define VCG_MATH_UNIONSET_H
|
#define VCG_MATH_UNIONSET_H
|
||||||
|
|
||||||
|
#include <unordered_map>
|
||||||
// some stuff for portable hashes...
|
|
||||||
#ifdef WIN32
|
|
||||||
#ifndef __MINGW32__
|
|
||||||
#include <hash_map>
|
|
||||||
#include <hash_set>
|
|
||||||
#define STDEXT stdext
|
|
||||||
#else
|
|
||||||
#include <ext/hash_map>
|
|
||||||
#include <ext/hash_set>
|
|
||||||
#define STDEXT __gnu_cxx
|
|
||||||
#endif
|
|
||||||
#else
|
|
||||||
#include <ext/hash_map>
|
|
||||||
#include <ext/hash_set>
|
|
||||||
#define STDEXT __gnu_cxx
|
|
||||||
// It's terrible but gnu's hash_map needs an instantiation of hash() for
|
|
||||||
// every key type! So we cast the pointer to void*
|
|
||||||
namespace __gnu_cxx
|
|
||||||
{
|
|
||||||
template <> class hash<void *>: private hash<unsigned long>
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
size_t operator()(const void *ptr) const { return hash<unsigned long>::operator()((unsigned long)ptr); }
|
|
||||||
};
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#include <vector>
|
#include <vector>
|
||||||
#include <assert.h>
|
#include <assert.h>
|
||||||
|
|
||||||
namespace vcg
|
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.
|
* 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 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.
|
* <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>
|
template<class OBJECT_TYPE>
|
||||||
class DisjointSet
|
class DisjointSet
|
||||||
{
|
{
|
||||||
/*************************************************
|
/*************************************************
|
||||||
* Inner class definitions
|
* Inner class definitions
|
||||||
**************************************************/
|
**************************************************/
|
||||||
struct DisjointSetNode
|
struct DisjointSetNode
|
||||||
{
|
{
|
||||||
DisjointSetNode(OBJECT_TYPE *x) {obj=x; parent=obj; rank=0;}
|
DisjointSetNode(OBJECT_TYPE *x) {obj=x; parent=obj; rank=0;}
|
||||||
OBJECT_TYPE *obj;
|
OBJECT_TYPE *obj;
|
||||||
OBJECT_TYPE *parent;
|
OBJECT_TYPE *parent;
|
||||||
int rank;
|
int rank;
|
||||||
};
|
};
|
||||||
|
|
||||||
typedef OBJECT_TYPE* ObjectPointer;
|
typedef OBJECT_TYPE* ObjectPointer;
|
||||||
typedef std::pair< ObjectPointer, int > hPair;
|
typedef std::pair< ObjectPointer, int > hPair;
|
||||||
|
|
||||||
struct SimpleObjHashFunc{
|
struct SimpleObjHashFunc{
|
||||||
inline size_t operator ()(const ObjectPointer &p) const {return size_t(p);}
|
inline size_t operator ()(const ObjectPointer &p) const {return size_t(p);}
|
||||||
};
|
};
|
||||||
|
|
||||||
#ifdef _MSC_VER
|
std::unordered_map< OBJECT_TYPE*, int > inserted_objects;
|
||||||
STDEXT::hash_map< OBJECT_TYPE*, int > inserted_objects;
|
typedef typename std::unordered_map< OBJECT_TYPE*, int >::iterator hIterator;
|
||||||
typedef typename STDEXT::hash_map< ObjectPointer, int >::iterator hIterator;
|
|
||||||
#else
|
|
||||||
STDEXT::hash_map< OBJECT_TYPE*, int, SimpleObjHashFunc > inserted_objects;
|
|
||||||
typedef typename STDEXT::hash_map< ObjectPointer, int, SimpleObjHashFunc >::iterator hIterator;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
typedef std::pair< hIterator, bool > hInsertResult;
|
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;
|
||||||
|
}
|
||||||
|
|
||||||
public:
|
private:
|
||||||
/*!
|
/*
|
||||||
* Default constructor
|
*/
|
||||||
*/
|
void Link(OBJECT_TYPE *x, OBJECT_TYPE *y)
|
||||||
DisjointSet() {}
|
{
|
||||||
|
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:
|
||||||
* Makes a group containing only a given element (a singleton).
|
std::vector< DisjointSetNode > nodes;
|
||||||
*/
|
};
|
||||||
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
|
};// end of namespace vcg
|
||||||
|
|
||||||
#endif //VCG_MATH_UNIONSET_H
|
#endif //VCG_MATH_UNIONSET_H
|
||||||
|
|
Loading…
Reference in New Issue