COIN-OR::LEMON - Graph Library

source: lemon-0.x/lemon/bits/array_map.h @ 1464:718207d6a1e6

Last change on this file since 1464:718207d6a1e6 was 1435:8e85e6bbefdf, checked in by Akos Ladanyi, 19 years ago

trunk/src/* move to trunk/

File size: 9.0 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>
[822]22
23///\ingroup graphmaps
24///\file
25///\brief Graph maps that construates and destruates
26///their elements dynamically.
27
[921]28namespace lemon {
[822]29
30
31  /// \addtogroup graphmaps
32  /// @{
33       
[1414]34  /// The ArrayMap template class is graph map structure what
35  /// automatically updates the map when a key is added to or erased from
36  /// the map. This map factory uses the allocators to implement
37  /// the container functionality.
38  ///
39  /// The template parameter is the AlterationNotifier that the maps
40  /// will belong to and the Value.
41   
[822]42
[946]43  template <typename _Graph,
44            typename _Item,
45            typename _Value>
[1039]46  class ArrayMap : public AlterationNotifier<_Item>::ObserverBase {
[897]47
[1267]48    typedef _Item Item;
[822]49  public:
50               
51    /// The graph type of the maps.
[946]52    typedef _Graph Graph;
[822]53    /// The key type of the maps.
[987]54    typedef _Item Key;
[946]55
[1039]56    typedef AlterationNotifier<_Item> Registry;
[946]57
[822]58    /// The MapBase of the Map which imlements the core regisitry function.
[946]59    typedef typename Registry::ObserverBase Parent;
[822]60               
61    /// The value type of the map.
[987]62    typedef _Value Value;
[822]63
64
[946]65  private:
[822]66    typedef std::allocator<Value> Allocator;
67
[946]68
69  public:
70
[1414]71    /// Graph and Registry initialized map constructor.
72     
[980]73    ArrayMap(const Graph& _g) : graph(&_g) {
[1267]74      Item it;
75      attach(_g.getNotifier(Item()));
[822]76      allocate_memory();
[1267]77      for (graph->first(it); it != INVALID; graph->next(it)) {
[980]78        int id = graph->id(it);;
[822]79        allocator.construct(&(values[id]), Value());
80      }                                                         
81    }
82
[946]83    /// Constructor to use default value to initialize the map.
84
85    /// It constrates a map and initialize all of the the map.
86
[980]87    ArrayMap(const Graph& _g, const Value& _v) : graph(&_g) {
[1267]88      Item it;
[1039]89      attach(_g.getNotifier(_Item()));
[822]90      allocate_memory();
[1267]91      for (graph->first(it); it != INVALID; graph->next(it)) {
[980]92        int id = graph->id(it);;
[946]93        allocator.construct(&(values[id]), _v);
[822]94      }                                                         
95    }
96
[1414]97    /// Constructor to copy a map of the same map type.
98     
[1374]99    ArrayMap(const ArrayMap& copy) : Parent() {
[946]100      if (copy.attached()) {
101        attach(*copy.getRegistry());
102      }
[822]103      capacity = copy.capacity;
104      if (capacity == 0) return;
105      values = allocator.allocate(capacity);
[1267]106      Item it;
107      for (graph->first(it); it != INVALID; graph->next(it)) {
[980]108        int id = graph->id(it);;
[891]109        allocator.construct(&(values[id]), copy.values[id]);
[822]110      }
111    }
112
[978]113    using Parent::attach;
114    using Parent::detach;
115    using Parent::attached;
116
[1414]117    /// Assign operator to copy a map of the same map type.
118     
[822]119    ArrayMap& operator=(const ArrayMap& copy) {
120      if (&copy == this) return *this;
[897]121     
[946]122      if (graph != copy.graph) {
123        if (attached()) {
124          clear();
125          detach();
[897]126        }
[946]127        if (copy.attached()) {
128          attach(*copy.getRegistry());
129        }
[897]130        capacity = copy.capacity;
131        if (capacity == 0) return *this;
132        values = allocator.allocate(capacity);     
[822]133      }
[891]134
[1267]135      Item it;
136      for (graph->first(it); it != INVALID; graph->next(it)) {
[980]137        int id = graph->id(it);;
[822]138        allocator.construct(&(values[id]), copy.values[id]);
139      }
[891]140
[822]141      return *this;
142    }
143
[1414]144    /// The destructor of the map.
145     
[946]146    virtual ~ArrayMap() {     
147      if (attached()) {
148        clear();
149        detach();
[822]150      }
151    }
152       
153       
[1414]154    ///The subscript operator. The map can be subscripted by the
155    ///actual keys of the graph.
156     
[1267]157    Value& operator[](const Key& key) {
[980]158      int id = graph->id(key);
[822]159      return values[id];
160    }
161               
[1414]162
163    ///The const subscript operator. The map can be subscripted by the
164    ///actual keys of the graph.
165     
[1267]166    const Value& operator[](const Key& key) const {
[980]167      int id = graph->id(key);
[822]168      return values[id];
169    }
170       
[1414]171    /// Setter function of the map. Equivalent with map[key] = val.
172    /// This is a compatibility feature with the not dereferable maps.
173     
[987]174    void set(const Key& key, const Value& val) {
[946]175      (*this)[key] = val;
[822]176    }
177               
[1414]178    /// Add a new key to the map. It called by the map registry.
179     
[987]180    void add(const Key& key) {
[980]181      int id = graph->id(key);
[822]182      if (id >= capacity) {
183        int new_capacity = (capacity == 0 ? 1 : capacity);
184        while (new_capacity <= id) {
185          new_capacity <<= 1;
186        }
[946]187        Value* new_values = allocator.allocate(new_capacity);
[1267]188        Item it;
189        for (graph->first(it); it != INVALID; graph->next(it)) {
[980]190          int jd = graph->id(it);;
[822]191          if (id != jd) {
192            allocator.construct(&(new_values[jd]), values[jd]);
193            allocator.destroy(&(values[jd]));
194          }
195        }
196        if (capacity != 0) allocator.deallocate(values, capacity);
197        values = new_values;
198        capacity = new_capacity;
199      }
200      allocator.construct(&(values[id]), Value());
201    }
[1414]202
203    void add(const std::vector<Key>& keys) {
204      int max_id = -1;
205      for (int i = 0; i < (int)keys.size(); ++i) {
206        int id = graph->id(keys[i]);
207        if (id > max_id) {
208          max_id = id;
209        }
210      }
211      if (max_id >= capacity) {
212        int new_capacity = (capacity == 0 ? 1 : capacity);
213        while (new_capacity <= max_id) {
214          new_capacity <<= 1;
215        }
216        Value* new_values = allocator.allocate(new_capacity);
217        Item it;
218        for (graph->first(it); it != INVALID; graph->next(it)) {
219          int id = graph->id(it);
220          bool found = false;
221          for (int i = 0; i < (int)keys.size(); ++i) {
222            int jd = graph->id(keys[i]);
223            if (id == jd) {
224              found = true;
225              break;
226            }
227          }
228          if (found) continue;
229          allocator.construct(&(new_values[id]), values[id]);
230          allocator.destroy(&(values[id]));
231        }
232        if (capacity != 0) allocator.deallocate(values, capacity);
233        values = new_values;
234        capacity = new_capacity;
235      }
236      for (int i = 0; i < (int)keys.size(); ++i) {
237        int id = graph->id(keys[i]);
238        allocator.construct(&(values[id]), Value());
239      }
240    }
[822]241               
[1414]242    /// Erase a key from the map. It called by the map registry.
243     
[987]244    void erase(const Key& key) {
[980]245      int id = graph->id(key);
[822]246      allocator.destroy(&(values[id]));
247    }
248
[1414]249    void erase(const std::vector<Key>& keys) {
250      for (int i = 0; i < (int)keys.size(); ++i) {
251        int id = graph->id(keys[i]);
252        allocator.destroy(&(values[id]));
253      }
254    }
255
[946]256    void build() {
257      allocate_memory();
[1267]258      Item it;
259      for (graph->first(it); it != INVALID; graph->next(it)) {
[980]260        int id = graph->id(it);;
[946]261        allocator.construct(&(values[id]), Value());
262      }                                                         
263    }
264
[822]265    void clear() {     
266      if (capacity != 0) {
[1267]267        Item it;
268        for (graph->first(it); it != INVALID; graph->next(it)) {
[1414]269          int id = graph->id(it);
[946]270          allocator.destroy(&(values[id]));
271        }                                                               
[822]272        allocator.deallocate(values, capacity);
273        capacity = 0;
274      }
275    }
276
[1271]277    const Graph* getGraph() {
278      return graph;
279    }
280
[822]281  private:
282     
283    void allocate_memory() {
[980]284      int max_id = graph->maxId(_Item());
[822]285      if (max_id == -1) {
286        capacity = 0;
287        values = 0;
288        return;
289      }
290      capacity = 1;
291      while (capacity <= max_id) {
292        capacity <<= 1;
293      }
294      values = allocator.allocate(capacity);   
295    }     
296
[946]297    const Graph* graph;
[822]298    int capacity;
299    Value* values;
300    Allocator allocator;
[844]301
[822]302  };           
303
[946]304  template <typename _Base>
305  class ArrayMappableGraphExtender : public _Base {
306  public:
307
308    typedef ArrayMappableGraphExtender<_Base> Graph;
309    typedef _Base Parent;
310
311    typedef typename Parent::Node Node;
312    typedef typename Parent::NodeIt NodeIt;
[1039]313    typedef typename Parent::NodeNotifier NodeObserverRegistry;
[946]314
315    typedef typename Parent::Edge Edge;
316    typedef typename Parent::EdgeIt EdgeIt;
[1039]317    typedef typename Parent::EdgeNotifier EdgeObserverRegistry;
[946]318
319   
320
321    template <typename _Value>
[1267]322    class NodeMap
323      : public IterableMapExtender<ArrayMap<Graph, Node, _Value> > {
[946]324    public:
325      typedef ArrayMappableGraphExtender<_Base> Graph;
326
327      typedef typename Graph::Node Node;
328      typedef typename Graph::NodeIt NodeIt;
329
[1267]330      typedef IterableMapExtender<ArrayMap<Graph, Node, _Value> > Parent;
[946]331
[979]332      //typedef typename Parent::Graph Graph;
[946]333      typedef typename Parent::Value Value;
334
335      NodeMap(const Graph& g)
[980]336        : Parent(g) {}
[946]337      NodeMap(const Graph& g, const Value& v)
[980]338        : Parent(g, v) {}
[946]339
340    };
341
342    template <typename _Value>
[1267]343    class EdgeMap
344      : public IterableMapExtender<ArrayMap<Graph, Edge, _Value> > {
[946]345    public:
346      typedef ArrayMappableGraphExtender<_Base> Graph;
347
348      typedef typename Graph::Edge Edge;
349      typedef typename Graph::EdgeIt EdgeIt;
350
[1267]351      typedef IterableMapExtender<ArrayMap<Graph, Edge, _Value> > Parent;
[946]352
[979]353      //typedef typename Parent::Graph Graph;
[946]354      typedef typename Parent::Value Value;
355
356      EdgeMap(const Graph& g)
[980]357        : Parent(g) {}
[946]358      EdgeMap(const Graph& g, const Value& v)
[980]359        : Parent(g, v) {}
[946]360
361    };
362   
363  };
364
[822]365/// @}
366
367}
368
[921]369#endif //LEMON_ARRAY_MAP_H
Note: See TracBrowser for help on using the repository browser.