00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024 #ifndef VCG_MATH_UNIONSET_H
00025 #define VCG_MATH_UNIONSET_H
00026
00027
00028
00029 #ifdef WIN32
00030 #ifndef __MINGW32__
00031 #include <hash_map>
00032 #include <hash_set>
00033 #define STDEXT stdext
00034 #else
00035 #include <ext/hash_map>
00036 #include <ext/hash_set>
00037 #define STDEXT __gnu_cxx
00038 #endif
00039 #else
00040 #include <ext/hash_map>
00041 #include <ext/hash_set>
00042 #define STDEXT __gnu_cxx
00043
00044
00045 namespace __gnu_cxx
00046 {
00047 template <> class hash<void *>: private hash<unsigned long>
00048 {
00049 public:
00050 size_t operator()(const void *ptr) const { return hash<unsigned long>::operator()((unsigned long)ptr); }
00051 };
00052 }
00053 #endif
00054
00055 #include <vector>
00056 #include <assert.h>
00057
00058 namespace vcg
00059 {
00065 template<class OBJECT_TYPE>
00066 class DisjointSet
00067 {
00068
00069
00070
00071 struct DisjointSetNode
00072 {
00073 DisjointSetNode(OBJECT_TYPE *x) {obj=x; parent=obj; rank=0;}
00074 OBJECT_TYPE *obj;
00075 OBJECT_TYPE *parent;
00076 int rank;
00077 };
00078
00079 typedef OBJECT_TYPE* ObjectPointer;
00080 typedef std::pair< ObjectPointer, int > hPair;
00081
00082 struct SimpleObjHashFunc{
00083 inline size_t operator ()(const ObjectPointer &p) const {return size_t(p);}
00084 };
00085
00086 #ifdef _MSC_VER
00087 STDEXT::hash_map< OBJECT_TYPE*, int > inserted_objects;
00088 typedef typename STDEXT::hash_map< ObjectPointer, int >::iterator hIterator;
00089 #else
00090 STDEXT::hash_map< OBJECT_TYPE*, int, SimpleObjHashFunc > inserted_objects;
00091 typedef typename STDEXT::hash_map< ObjectPointer, int, SimpleObjHashFunc >::iterator hIterator;
00092 #endif
00093
00094 typedef std::pair< hIterator, bool > hInsertResult;
00095
00096
00097
00098
00099
00100
00101 public:
00105 DisjointSet() {}
00106
00110 void MakeSet(OBJECT_TYPE *x)
00111 {
00112 int object_count = int(inserted_objects.size());
00113 assert(inserted_objects.find(x)==inserted_objects.end());
00114 nodes.push_back(DisjointSetNode(x));
00115 inserted_objects.insert( hPair(x,object_count) );
00116 }
00117
00121 void Union(OBJECT_TYPE *x, OBJECT_TYPE *y)
00122 {
00123 OBJECT_TYPE *s0 = FindSet(x);
00124 OBJECT_TYPE *s1 = FindSet(y);
00125 Link(s0, s1);
00126 }
00127
00131 OBJECT_TYPE* FindSet(OBJECT_TYPE *x)
00132 {
00133 hIterator pos = inserted_objects.find(x);
00134 assert(pos!=inserted_objects.end());
00135 DisjointSetNode *node = &nodes[pos->second];
00136 if (node->parent!=x)
00137 node->parent = FindSet(node->parent);
00138 return node->parent;
00139 }
00140
00141 private:
00142
00143
00144 void Link(OBJECT_TYPE *x, OBJECT_TYPE *y)
00145 {
00146 hIterator xPos = inserted_objects.find(x);
00147 hIterator yPos = inserted_objects.find(y);
00148 assert(xPos!=inserted_objects.end() && yPos!=inserted_objects.end());
00149 DisjointSetNode *xNode = &nodes[xPos->second];
00150 DisjointSetNode *yNode = &nodes[yPos->second];
00151 if (xNode->rank>yNode->rank)
00152 xNode->parent = y;
00153 else
00154 {
00155 yNode->parent = x;
00156 if (xNode->rank==yNode->rank)
00157 yNode->rank++;
00158 }
00159 }
00160
00161 protected:
00162 std::vector< DisjointSetNode > nodes;
00163 };
00164 };
00165
00166 #endif //VCG_MATH_UNIONSET_H