os/ossrv/ossrv_pub/boost_apis/boost/pending/disjoint_sets.hpp
author sl
Tue, 10 Jun 2014 14:32:02 +0200
changeset 1 260cb5ec6c19
permissions -rw-r--r--
Update contrib.
sl@0
     1
//
sl@0
     2
//=======================================================================
sl@0
     3
// Copyright 1997, 1998, 1999, 2000 University of Notre Dame.
sl@0
     4
// Authors: Andrew Lumsdaine, Lie-Quan Lee, Jeremy G. Siek
sl@0
     5
//
sl@0
     6
// Distributed under the Boost Software License, Version 1.0. (See
sl@0
     7
// accompanying file LICENSE_1_0.txt or copy at
sl@0
     8
// http://www.boost.org/LICENSE_1_0.txt)
sl@0
     9
//=======================================================================
sl@0
    10
//
sl@0
    11
#ifndef BOOST_DISJOINT_SETS_HPP
sl@0
    12
#define BOOST_DISJOINT_SETS_HPP
sl@0
    13
sl@0
    14
#include <vector>
sl@0
    15
#include <boost/graph/properties.hpp>
sl@0
    16
#include <boost/pending/detail/disjoint_sets.hpp>
sl@0
    17
sl@0
    18
namespace boost {
sl@0
    19
sl@0
    20
  struct find_with_path_halving {
sl@0
    21
    template <class ParentPA, class Vertex>
sl@0
    22
    Vertex operator()(ParentPA p, Vertex v) { 
sl@0
    23
      return detail::find_representative_with_path_halving(p, v);
sl@0
    24
    }
sl@0
    25
  };
sl@0
    26
sl@0
    27
  struct find_with_full_path_compression {
sl@0
    28
    template <class ParentPA, class Vertex>
sl@0
    29
    Vertex operator()(ParentPA p, Vertex v){
sl@0
    30
      return detail::find_representative_with_full_compression(p, v);
sl@0
    31
    }
sl@0
    32
  };
sl@0
    33
sl@0
    34
  // This is a generalized functor to provide disjoint sets operations
sl@0
    35
  // with "union by rank" and "path compression".  A disjoint-set data
sl@0
    36
  // structure maintains a collection S={S1, S2, ..., Sk} of disjoint
sl@0
    37
  // sets. Each set is identified by a representative, which is some
sl@0
    38
  // member of of the set. Sets are represented by rooted trees. Two
sl@0
    39
  // heuristics: "union by rank" and "path compression" are used to
sl@0
    40
  // speed up the operations.
sl@0
    41
sl@0
    42
  // Disjoint Set requires two vertex properties for internal use.  A
sl@0
    43
  // RankPA and a ParentPA. The RankPA must map Vertex to some Integral type
sl@0
    44
  // (preferably the size_type associated with Vertex). The ParentPA
sl@0
    45
  // must map Vertex to Vertex.
sl@0
    46
  template <class RankPA, class ParentPA,
sl@0
    47
    class FindCompress = find_with_full_path_compression
sl@0
    48
    >
sl@0
    49
  class disjoint_sets {
sl@0
    50
    typedef disjoint_sets self;
sl@0
    51
    
sl@0
    52
    inline disjoint_sets() {}
sl@0
    53
  public:
sl@0
    54
    inline disjoint_sets(RankPA r, ParentPA p) 
sl@0
    55
      : rank(r), parent(p) {}
sl@0
    56
sl@0
    57
    inline disjoint_sets(const self& c) 
sl@0
    58
      : rank(c.rank), parent(c.parent) {}
sl@0
    59
    
sl@0
    60
    // Make Set -- Create a singleton set containing vertex x
sl@0
    61
    template <class Element>
sl@0
    62
    inline void make_set(Element x)
sl@0
    63
    {
sl@0
    64
      put(parent, x, x);
sl@0
    65
      typedef typename property_traits<RankPA>::value_type R;
sl@0
    66
      put(rank, x, R());
sl@0
    67
    }
sl@0
    68
    
sl@0
    69
    // Link - union the two sets represented by vertex x and y
sl@0
    70
    template <class Element>
sl@0
    71
    inline void link(Element x, Element y)
sl@0
    72
    {
sl@0
    73
      detail::link_sets(parent, rank, x, y, rep);
sl@0
    74
    }
sl@0
    75
    
sl@0
    76
    // Union-Set - union the two sets containing vertex x and y 
sl@0
    77
    template <class Element>
sl@0
    78
    inline void union_set(Element x, Element y)
sl@0
    79
    {
sl@0
    80
      link(find_set(x), find_set(y));
sl@0
    81
    }
sl@0
    82
    
sl@0
    83
    // Find-Set - returns the Element representative of the set
sl@0
    84
    // containing Element x and applies path compression.
sl@0
    85
    template <class Element>
sl@0
    86
    inline Element find_set(Element x)
sl@0
    87
    {
sl@0
    88
      return rep(parent, x);
sl@0
    89
    }
sl@0
    90
sl@0
    91
    template <class ElementIterator>
sl@0
    92
    inline std::size_t count_sets(ElementIterator first, ElementIterator last)
sl@0
    93
    {
sl@0
    94
      std::size_t count = 0;  
sl@0
    95
      for ( ; first != last; ++first)
sl@0
    96
      if (get(parent, *first) == *first)
sl@0
    97
        ++count;
sl@0
    98
      return count;
sl@0
    99
    }
sl@0
   100
sl@0
   101
    template <class ElementIterator>
sl@0
   102
    inline void normalize_sets(ElementIterator first, ElementIterator last)
sl@0
   103
    {
sl@0
   104
      for (; first != last; ++first) 
sl@0
   105
        detail::normalize_node(parent, *first);
sl@0
   106
    }    
sl@0
   107
    
sl@0
   108
    template <class ElementIterator>
sl@0
   109
    inline void compress_sets(ElementIterator first, ElementIterator last)
sl@0
   110
    {
sl@0
   111
      for (; first != last; ++first) 
sl@0
   112
        detail::find_representative_with_full_compression(parent, *first);
sl@0
   113
    }    
sl@0
   114
  protected:
sl@0
   115
    RankPA rank;
sl@0
   116
    ParentPA parent;
sl@0
   117
    FindCompress rep;
sl@0
   118
  };
sl@0
   119
sl@0
   120
sl@0
   121
  
sl@0
   122
sl@0
   123
  template <class ID = identity_property_map,
sl@0
   124
            class InverseID = identity_property_map,
sl@0
   125
            class FindCompress = find_with_full_path_compression
sl@0
   126
            >
sl@0
   127
  class disjoint_sets_with_storage
sl@0
   128
  {
sl@0
   129
    typedef typename property_traits<ID>::value_type Index;
sl@0
   130
    typedef std::vector<Index> ParentContainer;
sl@0
   131
    typedef std::vector<unsigned char> RankContainer;
sl@0
   132
  public:
sl@0
   133
    typedef typename ParentContainer::size_type size_type;
sl@0
   134
sl@0
   135
    disjoint_sets_with_storage(size_type n = 0,
sl@0
   136
                               ID id_ = ID(),
sl@0
   137
                               InverseID inv = InverseID())
sl@0
   138
      : id(id_), id_to_vertex(inv), rank(n, 0), parent(n)
sl@0
   139
    {
sl@0
   140
      for (Index i = 0; i < n; ++i)
sl@0
   141
        parent[i] = i;
sl@0
   142
    }
sl@0
   143
    // note this is not normally needed
sl@0
   144
    template <class Element>
sl@0
   145
    inline void 
sl@0
   146
    make_set(Element x) {
sl@0
   147
      parent[x] = x;
sl@0
   148
      rank[x]   = 0;
sl@0
   149
    }
sl@0
   150
    template <class Element>
sl@0
   151
    inline void 
sl@0
   152
    link(Element x, Element y)
sl@0
   153
    {
sl@0
   154
      extend_sets(x,y);
sl@0
   155
      detail::link_sets(&parent[0], &rank[0], 
sl@0
   156
                        get(id,x), get(id,y), rep);
sl@0
   157
    }
sl@0
   158
    template <class Element>
sl@0
   159
    inline void 
sl@0
   160
    union_set(Element x, Element y) {
sl@0
   161
      Element rx = find_set(x);
sl@0
   162
      Element ry = find_set(y);
sl@0
   163
      link(rx, ry);
sl@0
   164
    }
sl@0
   165
    template <class Element>
sl@0
   166
    inline Element find_set(Element x) {
sl@0
   167
      return id_to_vertex[rep(&parent[0], get(id,x))];
sl@0
   168
    }
sl@0
   169
sl@0
   170
    template <class ElementIterator>
sl@0
   171
    inline std::size_t count_sets(ElementIterator first, ElementIterator last)
sl@0
   172
    {
sl@0
   173
      std::size_t count = 0;  
sl@0
   174
      for ( ; first != last; ++first)
sl@0
   175
      if (parent[*first] == *first)
sl@0
   176
        ++count;
sl@0
   177
      return count;
sl@0
   178
    }
sl@0
   179
sl@0
   180
    template <class ElementIterator>
sl@0
   181
    inline void normalize_sets(ElementIterator first, ElementIterator last)
sl@0
   182
    {
sl@0
   183
      for (; first != last; ++first) 
sl@0
   184
        detail::normalize_node(&parent[0], *first);
sl@0
   185
    }    
sl@0
   186
    
sl@0
   187
    template <class ElementIterator>
sl@0
   188
    inline void compress_sets(ElementIterator first, ElementIterator last)
sl@0
   189
    {
sl@0
   190
      for (; first != last; ++first) 
sl@0
   191
        detail::find_representative_with_full_compression(&parent[0],
sl@0
   192
                                                          *first);
sl@0
   193
    }    
sl@0
   194
sl@0
   195
    const ParentContainer& parents() { return parent; }
sl@0
   196
sl@0
   197
  protected:
sl@0
   198
sl@0
   199
    template <class Element>
sl@0
   200
    inline void 
sl@0
   201
    extend_sets(Element x, Element y)
sl@0
   202
    {
sl@0
   203
      Index needed = get(id,x) > get(id,y) ? get(id,x) + 1 : get(id,y) + 1;
sl@0
   204
      if (needed > parent.size()) {
sl@0
   205
        rank.insert(rank.end(), needed - rank.size(), 0);
sl@0
   206
        for (Index k = parent.size(); k < needed; ++k)
sl@0
   207
        parent.push_back(k);
sl@0
   208
      } 
sl@0
   209
    }
sl@0
   210
sl@0
   211
    ID id;
sl@0
   212
    InverseID id_to_vertex;
sl@0
   213
    RankContainer rank;
sl@0
   214
    ParentContainer parent;
sl@0
   215
    FindCompress rep;
sl@0
   216
  };
sl@0
   217
sl@0
   218
} // namespace boost
sl@0
   219
sl@0
   220
#endif // BOOST_DISJOINT_SETS_HPP