lemon/bits/array_map.h
author hegyi
Mon, 21 Nov 2005 18:03:20 +0000
changeset 1823 cb082cdf3667
parent 1810 474d093466a5
child 1875 98698b69a902
permissions -rw-r--r--
NewMapWin has become Dialog instead of Window. Therefore it is created dynamically, when there is need for it, instead of keeping one instance in memory. This solution is slower, but more correct than before.
alpar@906
     1
/* -*- C++ -*-
ladanyi@1435
     2
 * lemon/bits/array_map.h - Part of LEMON, a generic C++ optimization library
alpar@906
     3
 *
alpar@1164
     4
 * Copyright (C) 2005 Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport
alpar@1359
     5
 * (Egervary Research Group on Combinatorial Optimization, 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@1810
    21
#include <lemon/bits/map_extender.h>
deba@1813
    22
#include <lemon/bits/alteration_notifier.h>
deba@1669
    23
#include <lemon/concept_check.h>
deba@1669
    24
#include <lemon/concept/maps.h>
deba@822
    25
deba@1669
    26
/// \ingroup graphmapfactory
deba@1669
    27
/// \file
deba@1669
    28
/// \brief Graph maps that construct and destruct
deba@1669
    29
/// their elements dynamically.
deba@822
    30
alpar@921
    31
namespace lemon {
deba@822
    32
deba@1669
    33
  /// \ingroup graphmapfactory
deba@1669
    34
  ///
deba@1669
    35
  /// \brief Graph map based on the array storage.
deba@1669
    36
  ///
deba@1414
    37
  /// The ArrayMap template class is graph map structure what
deba@1414
    38
  /// automatically updates the map when a key is added to or erased from
deba@1669
    39
  /// the map. This map uses the allocators to implement 
deba@1414
    40
  /// the container functionality.
deba@1414
    41
  ///
deba@1414
    42
  /// The template parameter is the AlterationNotifier that the maps
deba@1414
    43
  /// will belong to and the Value.
deba@822
    44
klao@946
    45
  template <typename _Graph, 
klao@946
    46
	    typename _Item,
klao@946
    47
	    typename _Value>
deba@1039
    48
  class ArrayMap : public AlterationNotifier<_Item>::ObserverBase {
deba@897
    49
deba@1267
    50
    typedef _Item Item;
deba@822
    51
  public:
deba@822
    52
    /// The graph type of the maps. 
klao@946
    53
    typedef _Graph Graph;
deba@1719
    54
    /// The reference map tag.
deba@1719
    55
    typedef True ReferenceMapTag;
deba@1719
    56
deba@822
    57
    /// The key type of the maps.
alpar@987
    58
    typedef _Item Key;
deba@1719
    59
    /// The value type of the map.
deba@1719
    60
    typedef _Value Value;
deba@1719
    61
    /// The const reference type of the map.
deba@1719
    62
    typedef const _Value& ConstReference;
deba@1719
    63
    /// The reference type of the map.
deba@1719
    64
    typedef _Value& Reference;
deba@1719
    65
deba@1719
    66
    typedef const Value ConstValue;
deba@1719
    67
    typedef Value* Pointer;
deba@1719
    68
    typedef const Value* ConstPointer;
klao@946
    69
deba@1039
    70
    typedef AlterationNotifier<_Item> Registry;
klao@946
    71
deba@822
    72
    /// The MapBase of the Map which imlements the core regisitry function.
klao@946
    73
    typedef typename Registry::ObserverBase Parent;
deba@822
    74
		
deba@822
    75
deba@822
    76
klao@946
    77
  private:
deba@822
    78
    typedef std::allocator<Value> Allocator;
deba@822
    79
klao@946
    80
klao@946
    81
  public:
klao@946
    82
deba@1719
    83
    /// \brief Graph initialized map constructor.
deba@1703
    84
    ///
deba@1719
    85
    /// Graph initialized map constructor.
deba@980
    86
    ArrayMap(const Graph& _g) : graph(&_g) {
deba@1267
    87
      Item it;
deba@1267
    88
      attach(_g.getNotifier(Item()));
deba@822
    89
      allocate_memory();
deba@1267
    90
      for (graph->first(it); it != INVALID; graph->next(it)) {
deba@980
    91
	int id = graph->id(it);;
deba@822
    92
	allocator.construct(&(values[id]), Value());
deba@822
    93
      }								
deba@822
    94
    }
deba@822
    95
deba@1703
    96
    /// \brief Constructor to use default value to initialize the map. 
deba@1703
    97
    ///
deba@1703
    98
    /// It constructs a map and initialize all of the the map. 
deba@980
    99
    ArrayMap(const Graph& _g, const Value& _v) : graph(&_g) {
deba@1267
   100
      Item it;
deba@1039
   101
      attach(_g.getNotifier(_Item()));
deba@822
   102
      allocate_memory();
deba@1267
   103
      for (graph->first(it); it != INVALID; graph->next(it)) {
deba@980
   104
	int id = graph->id(it);;
klao@946
   105
	allocator.construct(&(values[id]), _v);
deba@822
   106
      }								
deba@822
   107
    }
deba@822
   108
deba@1703
   109
    /// \brief Constructor to copy a map of the same map type.
deba@1703
   110
    ///
deba@1703
   111
    /// Constructor to copy a map of the same map type.     
alpar@1613
   112
    ArrayMap(const ArrayMap& copy) : Parent(), graph(copy.graph) {
klao@946
   113
      if (copy.attached()) {
klao@946
   114
	attach(*copy.getRegistry());
klao@946
   115
      }
deba@822
   116
      capacity = copy.capacity;
deba@822
   117
      if (capacity == 0) return;
deba@822
   118
      values = allocator.allocate(capacity);
deba@1267
   119
      Item it;
deba@1267
   120
      for (graph->first(it); it != INVALID; graph->next(it)) {
deba@980
   121
	int id = graph->id(it);;
deba@891
   122
	allocator.construct(&(values[id]), copy.values[id]);
deba@822
   123
      }
deba@822
   124
    }
deba@822
   125
deba@1669
   126
    /// \brief The destructor of the map.
deba@1669
   127
    ///     
deba@1414
   128
    /// The destructor of the map.
klao@946
   129
    virtual ~ArrayMap() {      
klao@946
   130
      if (attached()) {
klao@946
   131
	clear();
klao@946
   132
	detach();
deba@822
   133
      }
deba@822
   134
    }
deba@1669
   135
		
deba@1669
   136
  private:
deba@1669
   137
deba@1669
   138
    ArrayMap& operator=(const ArrayMap&);
deba@1669
   139
deba@1669
   140
  protected:
deba@1669
   141
deba@1669
   142
    using Parent::attach;
deba@1669
   143
    using Parent::detach;
deba@1669
   144
    using Parent::attached;
deba@1669
   145
deba@1669
   146
    const Graph* getGraph() {
deba@1669
   147
      return graph;
deba@1669
   148
    }
deba@1669
   149
deba@1669
   150
deba@1669
   151
  public:
deba@1669
   152
deba@1703
   153
    /// \brief The subscript operator. 
deba@1703
   154
    ///
deba@1703
   155
    /// The subscript operator. The map can be subscripted by the
deba@1703
   156
    /// actual keys of the graph. 
deba@1267
   157
    Value& operator[](const Key& key) {
deba@980
   158
      int id = graph->id(key);
deba@822
   159
      return values[id];
deba@822
   160
    } 
deba@822
   161
		
deba@1703
   162
    /// \brief The const subscript operator.
deba@1703
   163
    ///
deba@1703
   164
    /// The const subscript operator. The map can be subscripted by the
deba@1703
   165
    /// actual keys of the graph. 
deba@1267
   166
    const Value& operator[](const Key& key) const {
deba@980
   167
      int id = graph->id(key);
deba@822
   168
      return values[id];
deba@822
   169
    }
deba@1703
   170
deba@1703
   171
    /// \brief Setter function of the map.
deba@1703
   172
    ///	
deba@1414
   173
    /// Setter function of the map. Equivalent with map[key] = val.
deba@1414
   174
    /// This is a compatibility feature with the not dereferable maps.
alpar@987
   175
    void set(const Key& key, const Value& val) {
klao@946
   176
      (*this)[key] = val;
deba@822
   177
    }
deba@1669
   178
deba@1669
   179
  protected:
deba@1703
   180
deba@1414
   181
    /// Add a new key to the map. It called by the map registry.
deba@1703
   182
         
deba@1703
   183
    virtual void add(const Key& key) {
deba@980
   184
      int id = graph->id(key);
deba@822
   185
      if (id >= capacity) {
deba@822
   186
	int new_capacity = (capacity == 0 ? 1 : capacity);
deba@822
   187
	while (new_capacity <= id) {
deba@822
   188
	  new_capacity <<= 1;
deba@822
   189
	}
klao@946
   190
	Value* new_values = allocator.allocate(new_capacity);
deba@1267
   191
	Item it;
deba@1267
   192
	for (graph->first(it); it != INVALID; graph->next(it)) {
deba@980
   193
	  int jd = graph->id(it);;
deba@822
   194
	  if (id != jd) {
deba@822
   195
	    allocator.construct(&(new_values[jd]), values[jd]);
deba@822
   196
	    allocator.destroy(&(values[jd]));
deba@822
   197
	  }
deba@822
   198
	}
deba@822
   199
	if (capacity != 0) allocator.deallocate(values, capacity);
deba@822
   200
	values = new_values;
deba@822
   201
	capacity = new_capacity;
deba@822
   202
      }
deba@822
   203
      allocator.construct(&(values[id]), Value());
deba@822
   204
    }
deba@1414
   205
deba@1703
   206
    virtual void add(const std::vector<Key>& keys) {
deba@1414
   207
      int max_id = -1;
deba@1414
   208
      for (int i = 0; i < (int)keys.size(); ++i) {
deba@1414
   209
	int id = graph->id(keys[i]);
deba@1414
   210
	if (id > max_id) {
deba@1414
   211
	  max_id = id;
deba@1414
   212
	}
deba@1414
   213
      }
deba@1414
   214
      if (max_id >= capacity) {
deba@1414
   215
	int new_capacity = (capacity == 0 ? 1 : capacity);
deba@1414
   216
	while (new_capacity <= max_id) {
deba@1414
   217
	  new_capacity <<= 1;
deba@1414
   218
	}
deba@1414
   219
	Value* new_values = allocator.allocate(new_capacity);
deba@1414
   220
	Item it;
deba@1414
   221
	for (graph->first(it); it != INVALID; graph->next(it)) {
deba@1414
   222
	  int id = graph->id(it);
deba@1414
   223
	  bool found = false;
deba@1414
   224
	  for (int i = 0; i < (int)keys.size(); ++i) {
deba@1414
   225
	    int jd = graph->id(keys[i]);
deba@1414
   226
	    if (id == jd) {
deba@1414
   227
	      found = true;
deba@1414
   228
	      break;
deba@1414
   229
	    }
deba@1414
   230
	  }
deba@1414
   231
	  if (found) continue;
deba@1414
   232
	  allocator.construct(&(new_values[id]), values[id]);
deba@1414
   233
	  allocator.destroy(&(values[id]));
deba@1414
   234
	}
deba@1414
   235
	if (capacity != 0) allocator.deallocate(values, capacity);
deba@1414
   236
	values = new_values;
deba@1414
   237
	capacity = new_capacity;
deba@1414
   238
      }
deba@1414
   239
      for (int i = 0; i < (int)keys.size(); ++i) {
deba@1414
   240
	int id = graph->id(keys[i]);
deba@1414
   241
	allocator.construct(&(values[id]), Value());
deba@1414
   242
      }
deba@1414
   243
    }
deba@822
   244
		
deba@1414
   245
    /// Erase a key from the map. It called by the map registry.
deba@1414
   246
     
deba@1703
   247
    virtual void erase(const Key& key) {
deba@980
   248
      int id = graph->id(key);
deba@822
   249
      allocator.destroy(&(values[id]));
deba@822
   250
    }
deba@822
   251
deba@1703
   252
    virtual void erase(const std::vector<Key>& keys) {
deba@1414
   253
      for (int i = 0; i < (int)keys.size(); ++i) {
deba@1414
   254
	int id = graph->id(keys[i]);
deba@1414
   255
	allocator.destroy(&(values[id]));
deba@1414
   256
      }
deba@1414
   257
    }
deba@1414
   258
deba@1703
   259
    virtual void build() {
klao@946
   260
      allocate_memory();
deba@1267
   261
      Item it;
deba@1267
   262
      for (graph->first(it); it != INVALID; graph->next(it)) {
deba@980
   263
	int id = graph->id(it);;
klao@946
   264
	allocator.construct(&(values[id]), Value());
klao@946
   265
      }								
klao@946
   266
    }
klao@946
   267
deba@1703
   268
    virtual void clear() {	
deba@822
   269
      if (capacity != 0) {
deba@1267
   270
	Item it;
deba@1267
   271
	for (graph->first(it); it != INVALID; graph->next(it)) {
deba@1414
   272
	  int id = graph->id(it);
klao@946
   273
	  allocator.destroy(&(values[id]));
klao@946
   274
	}								
deba@822
   275
	allocator.deallocate(values, capacity);
deba@822
   276
	capacity = 0;
deba@822
   277
      }
deba@822
   278
    }
deba@822
   279
deba@822
   280
  private:
deba@822
   281
      
deba@822
   282
    void allocate_memory() {
deba@980
   283
      int max_id = graph->maxId(_Item());
deba@822
   284
      if (max_id == -1) {
deba@822
   285
	capacity = 0;
deba@822
   286
	values = 0;
deba@822
   287
	return;
deba@822
   288
      }
deba@822
   289
      capacity = 1;
deba@822
   290
      while (capacity <= max_id) {
deba@822
   291
	capacity <<= 1;
deba@822
   292
      }
deba@822
   293
      values = allocator.allocate(capacity);	
deba@822
   294
    }      
deba@822
   295
klao@946
   296
    const Graph* graph;
deba@822
   297
    int capacity;
deba@822
   298
    Value* values;
deba@822
   299
    Allocator allocator;
deba@844
   300
deba@822
   301
  };		
deba@822
   302
deba@822
   303
}
deba@822
   304
alpar@921
   305
#endif //LEMON_ARRAY_MAP_H