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