src/lemon/array_map.h
author deba
Mon, 07 Feb 2005 10:48:14 +0000
changeset 1133 9fd485470fee
parent 988 aa19ca32d9b0
child 1164 80bb73097736
permissions -rw-r--r--
Documentation
alpar@906
     1
/* -*- C++ -*-
alpar@921
     2
 * src/lemon/array_map.h - Part of LEMON, a generic C++ optimization library
alpar@906
     3
 *
alpar@906
     4
 * Copyright (C) 2004 Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport
alpar@906
     5
 * (Egervary Combinatorial Optimization Research Group, EGRES).
alpar@906
     6
 *
alpar@906
     7
 * Permission to use, modify and distribute this software is granted
alpar@906
     8
 * provided that this copyright notice appears in all copies. For
alpar@906
     9
 * precise terms see the accompanying LICENSE file.
alpar@906
    10
 *
alpar@906
    11
 * This software is provided "AS IS" with no warranty of any kind,
alpar@906
    12
 * express or implied, and with no claim as to its suitability for any
alpar@906
    13
 * purpose.
alpar@906
    14
 *
alpar@906
    15
 */
alpar@906
    16
alpar@921
    17
#ifndef LEMON_ARRAY_MAP_H
alpar@921
    18
#define LEMON_ARRAY_MAP_H
deba@822
    19
deba@822
    20
#include <memory>
deba@822
    21
deba@822
    22
///\ingroup graphmaps
deba@822
    23
///\file
deba@822
    24
///\brief Graph maps that construates and destruates
deba@822
    25
///their elements dynamically.
deba@822
    26
alpar@921
    27
namespace lemon {
deba@822
    28
deba@822
    29
deba@822
    30
  /// \addtogroup graphmaps
deba@822
    31
  /// @{
deba@822
    32
	
deba@822
    33
  /** The ArrayMap template class is graph map structure what
deba@822
    34
   *  automatically updates the map when a key is added to or erased from
deba@822
    35
   *  the map. This map factory uses the allocators to implement 
deba@822
    36
   *  the container functionality.
deba@822
    37
   *
deba@822
    38
   *  The template parameter is the MapRegistry that the maps
alpar@987
    39
   *  will belong to and the Value.
deba@822
    40
   */
deba@822
    41
klao@946
    42
  template <typename _Graph, 
klao@946
    43
	    typename _Item,
klao@946
    44
	    typename _ItemIt,
klao@946
    45
	    typename _Value>
deba@1039
    46
  class ArrayMap : public AlterationNotifier<_Item>::ObserverBase {
deba@897
    47
deba@822
    48
  public:
deba@822
    49
		
deba@822
    50
    /// The graph type of the maps. 
klao@946
    51
    typedef _Graph Graph;
deba@822
    52
    /// The key type of the maps.
alpar@987
    53
    typedef _Item Key;
klao@946
    54
deba@1039
    55
    typedef AlterationNotifier<_Item> Registry;
klao@946
    56
klao@946
    57
  private:
deba@822
    58
    /// The iterator to iterate on the keys.
klao@946
    59
    typedef _ItemIt KeyIt;
klao@946
    60
deba@822
    61
    /// The MapBase of the Map which imlements the core regisitry function.
klao@946
    62
    typedef typename Registry::ObserverBase Parent;
deba@822
    63
		
deba@822
    64
    
deba@822
    65
  public:
deba@822
    66
deba@822
    67
    /// The value type of the map.
alpar@987
    68
    typedef _Value Value;
deba@822
    69
    /// The reference type of the map;
alpar@987
    70
    typedef Value& Reference;
deba@822
    71
    /// The pointer type of the map;
alpar@987
    72
    typedef Value* Pointer;
deba@822
    73
deba@822
    74
    /// The const value type of the map.
alpar@987
    75
    typedef const Value ConstValue;
deba@822
    76
    /// The const reference type of the map;
alpar@987
    77
    typedef const Value& ConstReference;
deba@822
    78
    /// The pointer type of the map;
alpar@987
    79
    typedef const Value* ConstPointer;
deba@822
    80
deba@822
    81
klao@946
    82
  private:
deba@822
    83
    typedef std::allocator<Value> Allocator;
deba@822
    84
klao@946
    85
klao@946
    86
  public:
klao@946
    87
deba@822
    88
    /** Graph and Registry initialized map constructor.
deba@822
    89
     */
deba@980
    90
    ArrayMap(const Graph& _g) : graph(&_g) {
deba@1039
    91
      attach(_g.getNotifier(_Item()));
deba@822
    92
      allocate_memory();
klao@946
    93
      for (KeyIt it(*graph); it != INVALID; ++it) {
deba@980
    94
	int id = graph->id(it);;
deba@822
    95
	allocator.construct(&(values[id]), Value());
deba@822
    96
      }								
deba@822
    97
    }
deba@822
    98
klao@946
    99
    /// Constructor to use default value to initialize the map. 
klao@946
   100
klao@946
   101
    /// It constrates a map and initialize all of the the map. 
klao@946
   102
deba@980
   103
    ArrayMap(const Graph& _g, const Value& _v) : graph(&_g) {
deba@1039
   104
      attach(_g.getNotifier(_Item()));
deba@822
   105
      allocate_memory();
klao@946
   106
      for (KeyIt it(*graph); it != INVALID; ++it) {
deba@980
   107
	int id = graph->id(it);;
klao@946
   108
	allocator.construct(&(values[id]), _v);
deba@822
   109
      }								
deba@822
   110
    }
deba@822
   111
deba@822
   112
    /** Constructor to copy a map of the same map type.
deba@822
   113
     */
klao@946
   114
    ArrayMap(const ArrayMap& copy) {
klao@946
   115
      if (copy.attached()) {
klao@946
   116
	attach(*copy.getRegistry());
klao@946
   117
      }
deba@822
   118
      capacity = copy.capacity;
deba@822
   119
      if (capacity == 0) return;
deba@822
   120
      values = allocator.allocate(capacity);
klao@946
   121
      for (KeyIt it(*graph); it != INVALID; ++it) {
deba@980
   122
	int id = graph->id(it);;
deba@891
   123
	allocator.construct(&(values[id]), copy.values[id]);
deba@822
   124
      }
deba@822
   125
    }
deba@822
   126
klao@978
   127
    using Parent::attach;
klao@978
   128
    using Parent::detach;
klao@978
   129
    using Parent::attached;
klao@978
   130
deba@822
   131
    /** Assign operator to copy a map of the same map type.
deba@822
   132
     */
deba@822
   133
    ArrayMap& operator=(const ArrayMap& copy) {
deba@822
   134
      if (&copy == this) return *this;
deba@897
   135
      
klao@946
   136
      if (graph != copy.graph) {
klao@946
   137
	if (attached()) {
klao@946
   138
	  clear();
klao@946
   139
	  detach();
deba@897
   140
	}
klao@946
   141
	if (copy.attached()) {
klao@946
   142
	  attach(*copy.getRegistry());
klao@946
   143
	}
deba@897
   144
	capacity = copy.capacity;
deba@897
   145
	if (capacity == 0) return *this;
deba@897
   146
	values = allocator.allocate(capacity);      
deba@822
   147
      }
deba@891
   148
klao@946
   149
      for (KeyIt it(*graph); it != INVALID; ++it) {
deba@980
   150
	int id = graph->id(it);;
deba@822
   151
	allocator.construct(&(values[id]), copy.values[id]);
deba@822
   152
      }
deba@891
   153
deba@822
   154
      return *this;
deba@822
   155
    }
deba@822
   156
deba@822
   157
    /** The destructor of the map.
deba@822
   158
     */
klao@946
   159
    virtual ~ArrayMap() {      
klao@946
   160
      if (attached()) {
klao@946
   161
	clear();
klao@946
   162
	detach();
deba@822
   163
      }
deba@822
   164
    }
deba@822
   165
	
deba@822
   166
	
deba@822
   167
    /**
deba@822
   168
     * The subscript operator. The map can be subscripted by the
deba@822
   169
     * actual keys of the graph. 
deba@822
   170
     */
alpar@987
   171
    Reference operator[](const Key& key) {
deba@980
   172
      int id = graph->id(key);
deba@822
   173
      return values[id];
deba@822
   174
    } 
deba@822
   175
		
deba@822
   176
    /**
deba@822
   177
     * The const subscript operator. The map can be subscripted by the
deba@822
   178
     * actual keys of the graph. 
deba@822
   179
     */
alpar@987
   180
    ConstReference operator[](const Key& key) const {
deba@980
   181
      int id = graph->id(key);
deba@822
   182
      return values[id];
deba@822
   183
    }
deba@822
   184
	
deba@822
   185
    /** Setter function of the map. Equivalent with map[key] = val.
deba@822
   186
     *  This is a compatibility feature with the not dereferable maps.
deba@822
   187
     */
alpar@987
   188
    void set(const Key& key, const Value& val) {
klao@946
   189
      (*this)[key] = val;
deba@822
   190
    }
deba@822
   191
		
deba@822
   192
    /** Add a new key to the map. It called by the map registry.
deba@822
   193
     */
alpar@987
   194
    void add(const Key& key) {
deba@980
   195
      int id = graph->id(key);
deba@822
   196
      if (id >= capacity) {
deba@822
   197
	int new_capacity = (capacity == 0 ? 1 : capacity);
deba@822
   198
	while (new_capacity <= id) {
deba@822
   199
	  new_capacity <<= 1;
deba@822
   200
	}
klao@946
   201
	Value* new_values = allocator.allocate(new_capacity);
klao@946
   202
	for (KeyIt it(*graph); it != INVALID; ++it) {
deba@980
   203
	  int jd = graph->id(it);;
deba@822
   204
	  if (id != jd) {
deba@822
   205
	    allocator.construct(&(new_values[jd]), values[jd]);
deba@822
   206
	    allocator.destroy(&(values[jd]));
deba@822
   207
	  }
deba@822
   208
	}
deba@822
   209
	if (capacity != 0) allocator.deallocate(values, capacity);
deba@822
   210
	values = new_values;
deba@822
   211
	capacity = new_capacity;
deba@822
   212
      }
deba@822
   213
      allocator.construct(&(values[id]), Value());
deba@822
   214
    }
deba@822
   215
		
deba@822
   216
    /** Erase a key from the map. It called by the map registry.
deba@822
   217
     */
alpar@987
   218
    void erase(const Key& key) {
deba@980
   219
      int id = graph->id(key);
deba@822
   220
      allocator.destroy(&(values[id]));
deba@822
   221
    }
deba@822
   222
klao@946
   223
    void build() {
klao@946
   224
      allocate_memory();
klao@946
   225
      for (KeyIt it(*graph); it != INVALID; ++it) {
deba@980
   226
	int id = graph->id(it);;
klao@946
   227
	allocator.construct(&(values[id]), Value());
klao@946
   228
      }								
klao@946
   229
    }
klao@946
   230
deba@822
   231
    void clear() {	
deba@822
   232
      if (capacity != 0) {
klao@946
   233
	for (KeyIt it(*graph); it != INVALID; ++it) {
deba@980
   234
	  int id = graph->id(it);;
klao@946
   235
	  allocator.destroy(&(values[id]));
klao@946
   236
	}								
deba@822
   237
	allocator.deallocate(values, capacity);
deba@822
   238
	capacity = 0;
deba@822
   239
      }
deba@822
   240
    }
deba@822
   241
klao@946
   242
//     /// The stl compatible pair iterator of the map.
klao@946
   243
//     typedef MapIterator<ArrayMap> Iterator;
klao@946
   244
//     /// The stl compatible const pair iterator of the map.
klao@946
   245
//     typedef MapConstIterator<ArrayMap> ConstIterator;
deba@822
   246
klao@946
   247
//     /** Returns the begin iterator of the map.
klao@946
   248
//      */
klao@946
   249
//     Iterator begin() {
klao@946
   250
//       return Iterator(*this, KeyIt(*MapBase::getGraph()));
klao@946
   251
//     }
deba@822
   252
klao@946
   253
//     /** Returns the end iterator of the map.
klao@946
   254
//      */
klao@946
   255
//     Iterator end() {
klao@946
   256
//       return Iterator(*this, INVALID);
klao@946
   257
//     }
deba@822
   258
klao@946
   259
//     /** Returns the begin ConstIterator of the map.
klao@946
   260
//      */
klao@946
   261
//     ConstIterator begin() const {
klao@946
   262
//       return ConstIterator(*this, KeyIt(*MapBase::getGraph()));
klao@946
   263
//     }
deba@822
   264
klao@946
   265
//     /** Returns the end const_iterator of the map.
klao@946
   266
//      */
klao@946
   267
//     ConstIterator end() const {
klao@946
   268
//       return ConstIterator(*this, INVALID);
klao@946
   269
//     }
deba@822
   270
klao@946
   271
//     /// The KeySet of the Map.
klao@946
   272
//     typedef MapConstKeySet<ArrayMap> ConstKeySet;
deba@830
   273
klao@946
   274
//     /// KeySet getter function.
klao@946
   275
//     ConstKeySet keySet() const {
klao@946
   276
//       return ConstKeySet(*this); 
klao@946
   277
//     }
deba@830
   278
klao@946
   279
//     /// The ConstValueSet of the Map.
klao@946
   280
//     typedef MapConstValueSet<ArrayMap> ConstValueSet;
deba@830
   281
klao@946
   282
//     /// ConstValueSet getter function.
klao@946
   283
//     ConstValueSet valueSet() const {
klao@946
   284
//       return ConstValueSet(*this);
klao@946
   285
//     }
deba@830
   286
klao@946
   287
//     /// The ValueSet of the Map.
klao@946
   288
//     typedef MapValueSet<ArrayMap> ValueSet;
deba@830
   289
klao@946
   290
//     /// ValueSet getter function.
klao@946
   291
//     ValueSet valueSet() {
klao@946
   292
//       return ValueSet(*this);
klao@946
   293
//     }
deba@830
   294
deba@822
   295
  private:
deba@822
   296
      
deba@822
   297
    void allocate_memory() {
deba@980
   298
      int max_id = graph->maxId(_Item());
deba@822
   299
      if (max_id == -1) {
deba@822
   300
	capacity = 0;
deba@822
   301
	values = 0;
deba@822
   302
	return;
deba@822
   303
      }
deba@822
   304
      capacity = 1;
deba@822
   305
      while (capacity <= max_id) {
deba@822
   306
	capacity <<= 1;
deba@822
   307
      }
deba@822
   308
      values = allocator.allocate(capacity);	
deba@822
   309
    }      
deba@822
   310
klao@946
   311
    const Graph* graph;
deba@822
   312
    int capacity;
deba@822
   313
    Value* values;
deba@822
   314
    Allocator allocator;
deba@844
   315
deba@844
   316
  public:
klao@946
   317
//     // STL  compatibility typedefs.
klao@946
   318
//     typedef Iterator iterator;
klao@946
   319
//     typedef ConstIterator const_iterator;
alpar@987
   320
//     typedef typename Iterator::PairValue value_type;
alpar@987
   321
//     typedef typename Iterator::Key key_type;
alpar@987
   322
//     typedef typename Iterator::Value data_type;
alpar@987
   323
//     typedef typename Iterator::PairReference reference;
alpar@987
   324
//     typedef typename Iterator::PairPointer pointer;
alpar@987
   325
//     typedef typename ConstIterator::PairReference const_reference;
alpar@987
   326
//     typedef typename ConstIterator::PairPointer const_pointer;
klao@946
   327
//     typedef int difference_type;		
deba@822
   328
  };		
deba@822
   329
klao@946
   330
  template <typename _Base> 
klao@946
   331
  class ArrayMappableGraphExtender : public _Base {
klao@946
   332
  public:
klao@946
   333
klao@946
   334
    typedef ArrayMappableGraphExtender<_Base> Graph;
klao@946
   335
    typedef _Base Parent;
klao@946
   336
klao@946
   337
    typedef typename Parent::Node Node;
klao@946
   338
    typedef typename Parent::NodeIt NodeIt;
deba@1039
   339
    typedef typename Parent::NodeNotifier NodeObserverRegistry;
klao@946
   340
klao@946
   341
    typedef typename Parent::Edge Edge;
klao@946
   342
    typedef typename Parent::EdgeIt EdgeIt;
deba@1039
   343
    typedef typename Parent::EdgeNotifier EdgeObserverRegistry;
klao@946
   344
klao@946
   345
    
klao@946
   346
klao@946
   347
    template <typename _Value>
deba@980
   348
    class NodeMap : public ArrayMap<Graph, Node, NodeIt, _Value> {
klao@946
   349
    public:
klao@946
   350
      typedef ArrayMappableGraphExtender<_Base> Graph;
klao@946
   351
klao@946
   352
      typedef typename Graph::Node Node;
klao@946
   353
      typedef typename Graph::NodeIt NodeIt;
klao@946
   354
deba@980
   355
      typedef ArrayMap<Graph, Node, NodeIt, _Value> Parent;
klao@946
   356
klao@979
   357
      //typedef typename Parent::Graph Graph;
klao@946
   358
      typedef typename Parent::Value Value;
klao@946
   359
klao@946
   360
      NodeMap(const Graph& g) 
deba@980
   361
	: Parent(g) {}
klao@946
   362
      NodeMap(const Graph& g, const Value& v) 
deba@980
   363
	: Parent(g, v) {}
klao@946
   364
klao@946
   365
    };
klao@946
   366
klao@946
   367
    template <typename _Value>
deba@980
   368
    class EdgeMap : public ArrayMap<Graph, Edge, EdgeIt, _Value> {
klao@946
   369
    public:
klao@946
   370
      typedef ArrayMappableGraphExtender<_Base> Graph;
klao@946
   371
klao@946
   372
      typedef typename Graph::Edge Edge;
klao@946
   373
      typedef typename Graph::EdgeIt EdgeIt;
klao@946
   374
deba@980
   375
      typedef ArrayMap<Graph, Edge, EdgeIt, _Value> Parent;
klao@946
   376
klao@979
   377
      //typedef typename Parent::Graph Graph;
klao@946
   378
      typedef typename Parent::Value Value;
klao@946
   379
klao@946
   380
      EdgeMap(const Graph& g) 
deba@980
   381
	: Parent(g) {}
klao@946
   382
      EdgeMap(const Graph& g, const Value& v) 
deba@980
   383
	: Parent(g, v) {}
klao@946
   384
klao@946
   385
    };
klao@946
   386
    
klao@946
   387
  };
klao@946
   388
deba@822
   389
/// @}
deba@822
   390
deba@822
   391
}
deba@822
   392
alpar@921
   393
#endif //LEMON_ARRAY_MAP_H