removed old style usage of hash map and substituted with c+11 sytle unordered set and map.

This commit is contained in:
Paolo Cignoni 2015-09-13 06:20:20 +00:00
parent ad95129d02
commit 47aaea332a
1 changed files with 86 additions and 122 deletions

View File

@ -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