COIN-OR::LEMON - Graph Library

source: lemon-0.x/lemon/bits/array_map.h @ 1703:eb90e3d6bddc

Last change on this file since 1703:eb90e3d6bddc was 1703:eb90e3d6bddc, checked in by Balazs Dezso, 19 years ago

Proper sized map type

File size: 7.5 KB
RevLine 
[906]1/* -*- C++ -*-
[1435]2 * lemon/bits/array_map.h - Part of LEMON, a generic C++ optimization library
[906]3 *
[1164]4 * Copyright (C) 2005 Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport
[1359]5 * (Egervary Research Group on Combinatorial Optimization, EGRES).
[906]6 *
7 * Permission to use, modify and distribute this software is granted
8 * provided that this copyright notice appears in all copies. For
9 * precise terms see the accompanying LICENSE file.
10 *
11 * This software is provided "AS IS" with no warranty of any kind,
12 * express or implied, and with no claim as to its suitability for any
13 * purpose.
14 *
15 */
16
[921]17#ifndef LEMON_ARRAY_MAP_H
18#define LEMON_ARRAY_MAP_H
[822]19
20#include <memory>
[1307]21#include <lemon/bits/map_iterator.h>
[1669]22#include <lemon/concept_check.h>
23#include <lemon/concept/maps.h>
[822]24
[1669]25/// \ingroup graphmapfactory
26/// \file
27/// \brief Graph maps that construct and destruct
28/// their elements dynamically.
[822]29
[921]30namespace lemon {
[822]31
[1669]32  /// \ingroup graphmapfactory
33  ///
34  /// \brief Graph map based on the array storage.
35  ///
[1414]36  /// The ArrayMap template class is graph map structure what
37  /// automatically updates the map when a key is added to or erased from
[1669]38  /// the map. This map uses the allocators to implement
[1414]39  /// the container functionality.
40  ///
41  /// The template parameter is the AlterationNotifier that the maps
42  /// will belong to and the Value.
[822]43
[946]44  template <typename _Graph,
45            typename _Item,
46            typename _Value>
[1039]47  class ArrayMap : public AlterationNotifier<_Item>::ObserverBase {
[897]48
[1267]49    typedef _Item Item;
[822]50  public:
[1703]51    typedef True AdaptibleTag;
[822]52               
53    /// The graph type of the maps.
[946]54    typedef _Graph Graph;
[822]55    /// The key type of the maps.
[987]56    typedef _Item Key;
[946]57
[1039]58    typedef AlterationNotifier<_Item> Registry;
[946]59
[822]60    /// The MapBase of the Map which imlements the core regisitry function.
[946]61    typedef typename Registry::ObserverBase Parent;
[822]62               
63    /// The value type of the map.
[987]64    typedef _Value Value;
[822]65
66
[946]67  private:
[822]68    typedef std::allocator<Value> Allocator;
69
[946]70
71  public:
72
[1703]73    /// \brief Graph and Registry initialized map constructor.
74    ///
[1414]75    /// Graph and Registry initialized map constructor.
[980]76    ArrayMap(const Graph& _g) : graph(&_g) {
[1267]77      Item it;
78      attach(_g.getNotifier(Item()));
[822]79      allocate_memory();
[1267]80      for (graph->first(it); it != INVALID; graph->next(it)) {
[980]81        int id = graph->id(it);;
[822]82        allocator.construct(&(values[id]), Value());
83      }                                                         
84    }
85
[1703]86    /// \brief Constructor to use default value to initialize the map.
87    ///
88    /// It constructs a map and initialize all of the the map.
[980]89    ArrayMap(const Graph& _g, const Value& _v) : graph(&_g) {
[1267]90      Item it;
[1039]91      attach(_g.getNotifier(_Item()));
[822]92      allocate_memory();
[1267]93      for (graph->first(it); it != INVALID; graph->next(it)) {
[980]94        int id = graph->id(it);;
[946]95        allocator.construct(&(values[id]), _v);
[822]96      }                                                         
97    }
98
[1703]99    /// \brief Constructor to copy a map of the same map type.
100    ///
101    /// Constructor to copy a map of the same map type.     
[1613]102    ArrayMap(const ArrayMap& copy) : Parent(), graph(copy.graph) {
[946]103      if (copy.attached()) {
104        attach(*copy.getRegistry());
105      }
[822]106      capacity = copy.capacity;
107      if (capacity == 0) return;
108      values = allocator.allocate(capacity);
[1267]109      Item it;
110      for (graph->first(it); it != INVALID; graph->next(it)) {
[980]111        int id = graph->id(it);;
[891]112        allocator.construct(&(values[id]), copy.values[id]);
[822]113      }
114    }
115
[1669]116    /// \brief The destructor of the map.
117    ///     
[1414]118    /// The destructor of the map.
[946]119    virtual ~ArrayMap() {     
120      if (attached()) {
121        clear();
122        detach();
[822]123      }
124    }
[1669]125               
126  private:
127
128    ArrayMap& operator=(const ArrayMap&);
129
130  protected:
131
132    using Parent::attach;
133    using Parent::detach;
134    using Parent::attached;
135
136    const Graph* getGraph() {
137      return graph;
138    }
139
140
141  public:
142
[1703]143    /// \brief The subscript operator.
144    ///
145    /// The subscript operator. The map can be subscripted by the
146    /// actual keys of the graph.
[1267]147    Value& operator[](const Key& key) {
[980]148      int id = graph->id(key);
[822]149      return values[id];
150    }
151               
[1703]152    /// \brief The const subscript operator.
153    ///
154    /// The const subscript operator. The map can be subscripted by the
155    /// actual keys of the graph.
[1267]156    const Value& operator[](const Key& key) const {
[980]157      int id = graph->id(key);
[822]158      return values[id];
159    }
[1703]160
161    /// \brief Setter function of the map.
162    ///
[1414]163    /// Setter function of the map. Equivalent with map[key] = val.
164    /// This is a compatibility feature with the not dereferable maps.
[987]165    void set(const Key& key, const Value& val) {
[946]166      (*this)[key] = val;
[822]167    }
[1669]168
169  protected:
[1703]170
[1414]171    /// Add a new key to the map. It called by the map registry.
[1703]172         
173    virtual void add(const Key& key) {
[980]174      int id = graph->id(key);
[822]175      if (id >= capacity) {
176        int new_capacity = (capacity == 0 ? 1 : capacity);
177        while (new_capacity <= id) {
178          new_capacity <<= 1;
179        }
[946]180        Value* new_values = allocator.allocate(new_capacity);
[1267]181        Item it;
182        for (graph->first(it); it != INVALID; graph->next(it)) {
[980]183          int jd = graph->id(it);;
[822]184          if (id != jd) {
185            allocator.construct(&(new_values[jd]), values[jd]);
186            allocator.destroy(&(values[jd]));
187          }
188        }
189        if (capacity != 0) allocator.deallocate(values, capacity);
190        values = new_values;
191        capacity = new_capacity;
192      }
193      allocator.construct(&(values[id]), Value());
194    }
[1414]195
[1703]196    virtual void add(const std::vector<Key>& keys) {
[1414]197      int max_id = -1;
198      for (int i = 0; i < (int)keys.size(); ++i) {
199        int id = graph->id(keys[i]);
200        if (id > max_id) {
201          max_id = id;
202        }
203      }
204      if (max_id >= capacity) {
205        int new_capacity = (capacity == 0 ? 1 : capacity);
206        while (new_capacity <= max_id) {
207          new_capacity <<= 1;
208        }
209        Value* new_values = allocator.allocate(new_capacity);
210        Item it;
211        for (graph->first(it); it != INVALID; graph->next(it)) {
212          int id = graph->id(it);
213          bool found = false;
214          for (int i = 0; i < (int)keys.size(); ++i) {
215            int jd = graph->id(keys[i]);
216            if (id == jd) {
217              found = true;
218              break;
219            }
220          }
221          if (found) continue;
222          allocator.construct(&(new_values[id]), values[id]);
223          allocator.destroy(&(values[id]));
224        }
225        if (capacity != 0) allocator.deallocate(values, capacity);
226        values = new_values;
227        capacity = new_capacity;
228      }
229      for (int i = 0; i < (int)keys.size(); ++i) {
230        int id = graph->id(keys[i]);
231        allocator.construct(&(values[id]), Value());
232      }
233    }
[822]234               
[1414]235    /// Erase a key from the map. It called by the map registry.
236     
[1703]237    virtual void erase(const Key& key) {
[980]238      int id = graph->id(key);
[822]239      allocator.destroy(&(values[id]));
240    }
241
[1703]242    virtual void erase(const std::vector<Key>& keys) {
[1414]243      for (int i = 0; i < (int)keys.size(); ++i) {
244        int id = graph->id(keys[i]);
245        allocator.destroy(&(values[id]));
246      }
247    }
248
[1703]249    virtual void build() {
[946]250      allocate_memory();
[1267]251      Item it;
252      for (graph->first(it); it != INVALID; graph->next(it)) {
[980]253        int id = graph->id(it);;
[946]254        allocator.construct(&(values[id]), Value());
255      }                                                         
256    }
257
[1703]258    virtual void clear() {     
[822]259      if (capacity != 0) {
[1267]260        Item it;
261        for (graph->first(it); it != INVALID; graph->next(it)) {
[1414]262          int id = graph->id(it);
[946]263          allocator.destroy(&(values[id]));
264        }                                                               
[822]265        allocator.deallocate(values, capacity);
266        capacity = 0;
267      }
268    }
269
270  private:
271     
272    void allocate_memory() {
[980]273      int max_id = graph->maxId(_Item());
[822]274      if (max_id == -1) {
275        capacity = 0;
276        values = 0;
277        return;
278      }
279      capacity = 1;
280      while (capacity <= max_id) {
281        capacity <<= 1;
282      }
283      values = allocator.allocate(capacity);   
284    }     
285
[946]286    const Graph* graph;
[822]287    int capacity;
288    Value* values;
289    Allocator allocator;
[844]290
[822]291  };           
292
293}
294
[921]295#endif //LEMON_ARRAY_MAP_H
Note: See TracBrowser for help on using the repository browser.