BWAPI
SPAR/AIModule/BWTA/vendors/CGAL/CGAL/Union_find.h
Go to the documentation of this file.
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 
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines