BWAPI
|
00001 // Copyright (c) 1997-2000 Utrecht University (The Netherlands), 00002 // ETH Zurich (Switzerland), Freie Universitaet Berlin (Germany), 00003 // INRIA Sophia-Antipolis (France), Martin-Luther-University Halle-Wittenberg 00004 // (Germany), Max-Planck-Institute Saarbruecken (Germany), RISC Linz (Austria), 00005 // and Tel-Aviv University (Israel). All rights reserved. 00006 // 00007 // This file is part of CGAL (www.cgal.org); you can redistribute it and/or 00008 // modify it under the terms of the GNU Lesser General Public License as 00009 // published by the Free Software Foundation; version 2.1 of the License. 00010 // See the file LICENSE.LGPL distributed with CGAL. 00011 // 00012 // Licensees holding a valid commercial license may use this file in 00013 // accordance with the commercial license agreement provided with the software. 00014 // 00015 // This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE 00016 // WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. 00017 // 00018 // $URL: svn+ssh://scm.gforge.inria.fr/svn/cgal/branches/CGAL-3.5-branch/Union_find/include/CGAL/Union_find.h $ 00019 // $Id: Union_find.h 46254 2008-10-14 07:23:48Z afabri $ 00020 // 00021 // 00022 // Author(s) : Michael Seel <seel@mpi-sb.mpg.de>, 00023 // Lutz Kettner <kettner@mpi-sb.mpg.de> 00024 00025 00026 #ifndef CGAL_UNION_FIND_H 00027 #define CGAL_UNION_FIND_H 00028 00029 #include <CGAL/basic.h> 00030 #include <CGAL/memory.h> 00031 #include <cstddef> 00032 00033 CGAL_BEGIN_NAMESPACE 00034 00035 namespace CGALi { 00036 00037 template <class PTR_, class V_, class R_, class P_> 00038 class UF_forward_iterator { 00039 PTR_ m_p; 00040 public: 00041 // should be private and Union_find<...> a friend. 00042 PTR_ ptr() const { return m_p; } 00043 00044 typedef UF_forward_iterator<PTR_, V_, R_, P_> Self; 00045 typedef V_ value_type; 00046 typedef R_ reference; 00047 typedef P_ pointer; 00048 typedef std::forward_iterator_tag iterator_category; 00049 00050 UF_forward_iterator() : m_p(0) {} 00051 UF_forward_iterator(PTR_ p) : m_p(p) {} 00052 00053 // Allows construction of const_iterator from iterator 00054 template <class PPTR, class VV, class RR, class PP> 00055 UF_forward_iterator(const UF_forward_iterator<PPTR, VV, RR, PP>& i) 00056 : m_p(i.ptr()) {} 00057 00058 bool operator==( const Self& x) const { return m_p == x.m_p; } 00059 bool operator!=( const Self& x) const { return !(*this == x); } 00060 reference operator*() const { return m_p->value; } 00061 pointer operator->() const { return &(m_p->value); } 00062 Self& operator++() { 00063 CGAL_assertion(m_p != 0); 00064 m_p = m_p->next; 00065 return *this; 00066 } 00067 Self operator++(int) { 00068 Self tmp = *this; 00069 ++*this; 00070 return tmp; 00071 } 00072 }; 00073 00074 } // CGALi 00075 00076 00077 // Union-Find with path compression. 00078 // -------------------------------------------------------------------- 00079 // An instance of the data type Union_find is a partition of values of 00080 // type |T| into disjoint sets. The type |A| has to be a model of the 00081 // allocator concept as defined in the C++ standard. 00082 00083 // Union_find is implemented with union by rank and path compression. 00084 // The running time for $m$ set operations on $n$ elements is 00085 // $O(n \alpha(m,n))$ where $\alpha(m,n)$ is the extremely slow 00086 // growing inverse of Ackermann's function. 00087 00088 template <typename T, typename A = CGAL_ALLOCATOR(T) > 00089 class Union_find { 00090 struct Union_find_struct { 00091 typedef Union_find_struct* pointer; 00092 // friend class Union_find<T,A>; 00093 mutable pointer up; 00094 pointer next; 00095 std::size_t size; 00096 T value; 00097 Union_find_struct( pointer n, const T& x) 00098 : up(0), next(n), size(1), value(x) {} 00099 }; 00100 00101 public: 00102 typedef Union_find<T,A> Self; 00103 typedef Union_find_struct* pointer; 00104 typedef const Union_find_struct* const_pointer; 00105 00106 typedef T value_type; 00107 typedef T& reference; 00108 typedef const T& const_reference; 00109 00110 typedef CGALi::UF_forward_iterator< pointer, T, T&, T*> iterator; 00111 typedef iterator handle; 00112 typedef CGALi::UF_forward_iterator< const_pointer, T, const T&, const T*> 00113 const_iterator; 00114 typedef const_iterator const_handle; 00115 00116 #ifdef _MSC_VER 00117 typedef CGAL_ALLOCATOR(Union_find_struct) allocator; 00118 #else 00119 typedef typename A::template rebind<Union_find_struct> Rebind; 00120 typedef typename Rebind::other allocator; 00121 #endif 00122 00123 private: 00124 pointer m_first; 00125 std::size_t sets; 00126 std::size_t values; 00127 allocator alloc; 00128 00129 // Private decl. and no definition, thus no copy constructor 00130 // and no assignment for this class. 00131 Union_find(const Self&); 00132 Self& operator=(const Self&); 00133 00134 pointer find( pointer p) const { 00135 CGAL_assertion(p != 0); 00136 pointer r = p; 00137 while (r->up) 00138 r = r->up; // now r is the root; 00139 while (p->up) { 00140 pointer u = p->up; 00141 p->up = r; // path compression: assign root r as new parent 00142 p = u; // this would need the 'mutable' for the up field 00143 } // if we would have a const_pointer, see the cast 00144 return r; // in the fct. below. We keep the mutable as reminder. 00145 } 00146 const_pointer find( const_pointer p ) const { 00147 return find( const_cast<pointer>(p)); 00148 } 00149 bool is_valid(const_handle v) const { return v != const_handle(0); } 00150 00151 public: 00152 Union_find() : m_first(0), sets(0), values(0) {} 00153 ~Union_find() { clear(); } 00154 00155 allocator get_allocator() const { return alloc; } 00156 00157 std::size_t number_of_sets() const { return sets; } 00158 // returns the number of disjoint sets 00159 00160 std::size_t size() const { return values; } 00161 // returns the number of values 00162 00163 std::size_t bytes() const { 00164 // returns the memory consumed 00165 return values * sizeof(Union_find_struct) + sizeof( Self); 00166 } 00167 00168 std::size_t size( const_handle p) const { return find(p).ptr()->size; } 00169 // returns the size of the set containing $p$ 00170 00171 void clear(); 00172 // reinitializes to an empty partition 00173 00174 handle make_set(const T& x); 00175 // creates a new singleton set containing |x| and returns a handle to it 00176 00177 handle push_back(const T& x) { return make_set(x); } 00178 // same as |make_set(x)| 00179 00180 template <class Forward_iterator> 00181 void insert( Forward_iterator first, Forward_iterator beyond) { 00182 // insert the range of values referenced by |[first,beyond)|. 00183 // Precond: value type of |Forward_iterator| is |T|. 00184 while (first != beyond) 00185 push_back(*first++); 00186 } 00187 00188 handle find( handle p) const { return find(p.ptr()); } 00189 00190 const_handle find( const_handle p ) const { 00191 // returns a canonical handle of the set that contains |p|, 00192 // i.e., |P.same_set(p,q)| iff |P.find(p)| and |P.find(q)| return 00193 // the same handle. Precond: |p| is a handle in the union find structure. 00194 return find(p.ptr()); 00195 } 00196 00197 void unify_sets(handle p, handle q); 00198 // unites the sets of partition containing $p$ and $q$. 00199 // Precond: $p$ and $q$ are in the partition. 00200 00201 bool same_set( const_handle p, const_handle q) const { 00202 // returns true iff $p$ and $q$ belong to the same set. 00203 // Precond: $p$ and $q$ are in the partition. 00204 return find(p) == find(q); 00205 } 00206 00207 iterator begin() { return iterator(m_first); } 00208 iterator end() { return iterator(0); } 00209 00210 const_iterator begin() const { return const_iterator(m_first); } 00211 const_iterator end() const { return const_iterator(0); } 00212 }; 00213 00214 template <typename T, typename A> 00215 typename Union_find<T,A>::handle Union_find<T,A>::make_set(const T& x) { 00216 pointer tmp = m_first; 00217 m_first = alloc.allocate(1); 00218 alloc.construct( m_first, Union_find_struct(tmp,x)); 00219 ++sets; 00220 ++values; 00221 return handle( m_first); 00222 } 00223 00224 template <typename T, typename A> 00225 void Union_find<T,A>::clear() { 00226 while (m_first) { 00227 pointer tmp = m_first->next; 00228 alloc.destroy(m_first); 00229 alloc.deallocate(m_first,1); 00230 m_first = tmp; 00231 } 00232 sets = 0; 00233 values = 0; 00234 } 00235 00236 template <typename T, typename A> 00237 void Union_find<T,A>::unify_sets( handle p, handle q) { 00238 CGAL_assertion( is_valid(p) && is_valid(q)); 00239 pointer pit = find( p.ptr()); 00240 pointer qit = find( q.ptr()); 00241 if (pit == qit) 00242 return; 00243 std::size_t sp = pit->size; 00244 std::size_t sq = qit->size; 00245 if (sp > sq) 00246 std::swap(pit,qit); // now sp <= sq 00247 pit->up = qit; // linking roots 00248 qit->size += pit->size; // updating size 00249 --sets; 00250 } 00251 00252 CGAL_END_NAMESPACE 00253 00254 #endif // CGAL_UNION_FIND_H 00255