3 * This file is a part of LEMON, a generic C++ optimization library
5 * Copyright (C) 2003-2006
6 * Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport
7 * (Egervary Research Group on Combinatorial Optimization, EGRES).
9 * Permission to use, modify and distribute this software is granted
10 * provided that this copyright notice appears in all copies. For
11 * precise terms see the accompanying LICENSE file.
13 * This software is provided "AS IS" with no warranty of any kind,
14 * express or implied, and with no claim as to its suitability for any
19 #ifndef LEMON_ARRAY_MAP_H
20 #define LEMON_ARRAY_MAP_H
23 #include <lemon/bits/map_extender.h>
24 #include <lemon/bits/alteration_notifier.h>
25 #include <lemon/concept_check.h>
26 #include <lemon/concept/maps.h>
28 /// \ingroup graphmapfactory
30 /// \brief Graph maps that construct and destruct
31 /// their elements dynamically.
35 /// \ingroup graphmapfactory
37 /// \brief Graph map based on the array storage.
39 /// The ArrayMap template class is graph map structure what
40 /// automatically indates the map when a key is added to or erased from
41 /// the map. This map uses the allocators to implement
42 /// the container functionality.
44 /// The template parameter is the AlterationNotifier that the maps
45 /// will belong to and the Value.
47 template <typename _Graph,
50 class ArrayMap : public AlterationNotifier<_Item>::ObserverBase {
54 /// The graph type of the maps.
56 /// The reference map tag.
57 typedef True ReferenceMapTag;
59 /// The key type of the maps.
61 /// The value type of the map.
63 /// The const reference type of the map.
64 typedef const _Value& ConstReference;
65 /// The reference type of the map.
66 typedef _Value& Reference;
68 typedef const Value ConstValue;
69 typedef Value* Pointer;
70 typedef const Value* ConstPointer;
72 typedef AlterationNotifier<_Item> Registry;
74 /// The MapBase of the Map which imlements the core regisitry function.
75 typedef typename Registry::ObserverBase Parent;
80 typedef std::allocator<Value> Allocator;
85 /// \brief Graph initialized map constructor.
87 /// Graph initialized map constructor.
88 ArrayMap(const Graph& _g) : graph(&_g) {
90 attach(_g.getNotifier(Item()));
92 for (graph->first(it); it != INVALID; graph->next(it)) {
93 int id = graph->id(it);;
94 allocator.construct(&(values[id]), Value());
98 /// \brief Constructor to use default value to initialize the map.
100 /// It constructs a map and initialize all of the the map.
101 ArrayMap(const Graph& _g, const Value& _v) : graph(&_g) {
103 attach(_g.getNotifier(_Item()));
105 for (graph->first(it); it != INVALID; graph->next(it)) {
106 int id = graph->id(it);;
107 allocator.construct(&(values[id]), _v);
111 /// \brief Constructor to copy a map of the same map type.
113 /// Constructor to copy a map of the same map type.
114 ArrayMap(const ArrayMap& copy) : Parent(), graph(copy.graph) {
115 if (copy.attached()) {
116 attach(*copy.getRegistry());
118 capacity = copy.capacity;
119 if (capacity == 0) return;
120 values = allocator.allocate(capacity);
122 for (graph->first(it); it != INVALID; graph->next(it)) {
123 int id = graph->id(it);;
124 allocator.construct(&(values[id]), copy.values[id]);
128 /// \brief The destructor of the map.
130 /// The destructor of the map.
131 virtual ~ArrayMap() {
140 ArrayMap& operator=(const ArrayMap&);
144 using Parent::attach;
145 using Parent::detach;
146 using Parent::attached;
148 const Graph* getGraph() {
155 /// \brief The subscript operator.
157 /// The subscript operator. The map can be subscripted by the
158 /// actual keys of the graph.
159 Value& operator[](const Key& key) {
160 int id = graph->id(key);
164 /// \brief The const subscript operator.
166 /// The const subscript operator. The map can be subscripted by the
167 /// actual keys of the graph.
168 const Value& operator[](const Key& key) const {
169 int id = graph->id(key);
173 /// \brief Setter function of the map.
175 /// Setter function of the map. Equivalent with map[key] = val.
176 /// This is a compatibility feature with the not dereferable maps.
177 void set(const Key& key, const Value& val) {
183 /// Add a new key to the map. It called by the map registry.
185 virtual void add(const Key& key) {
186 int id = graph->id(key);
187 if (id >= capacity) {
188 int new_capacity = (capacity == 0 ? 1 : capacity);
189 while (new_capacity <= id) {
192 Value* new_values = allocator.allocate(new_capacity);
194 for (graph->first(it); it != INVALID; graph->next(it)) {
195 int jd = graph->id(it);;
197 allocator.construct(&(new_values[jd]), values[jd]);
198 allocator.destroy(&(values[jd]));
201 if (capacity != 0) allocator.deallocate(values, capacity);
203 capacity = new_capacity;
205 allocator.construct(&(values[id]), Value());
208 virtual void add(const std::vector<Key>& keys) {
210 for (int i = 0; i < (int)keys.size(); ++i) {
211 int id = graph->id(keys[i]);
216 if (max_id >= capacity) {
217 int new_capacity = (capacity == 0 ? 1 : capacity);
218 while (new_capacity <= max_id) {
221 Value* new_values = allocator.allocate(new_capacity);
223 for (graph->first(it); it != INVALID; graph->next(it)) {
224 int id = graph->id(it);
226 for (int i = 0; i < (int)keys.size(); ++i) {
227 int jd = graph->id(keys[i]);
234 allocator.construct(&(new_values[id]), values[id]);
235 allocator.destroy(&(values[id]));
237 if (capacity != 0) allocator.deallocate(values, capacity);
239 capacity = new_capacity;
241 for (int i = 0; i < (int)keys.size(); ++i) {
242 int id = graph->id(keys[i]);
243 allocator.construct(&(values[id]), Value());
247 /// Erase a key from the map. It called by the map registry.
249 virtual void erase(const Key& key) {
250 int id = graph->id(key);
251 allocator.destroy(&(values[id]));
254 virtual void erase(const std::vector<Key>& keys) {
255 for (int i = 0; i < (int)keys.size(); ++i) {
256 int id = graph->id(keys[i]);
257 allocator.destroy(&(values[id]));
261 virtual void build() {
264 for (graph->first(it); it != INVALID; graph->next(it)) {
265 int id = graph->id(it);;
266 allocator.construct(&(values[id]), Value());
270 virtual void clear() {
273 for (graph->first(it); it != INVALID; graph->next(it)) {
274 int id = graph->id(it);
275 allocator.destroy(&(values[id]));
277 allocator.deallocate(values, capacity);
284 void allocate_memory() {
285 int max_id = graph->maxId(_Item());
292 while (capacity <= max_id) {
295 values = allocator.allocate(capacity);
307 #endif //LEMON_ARRAY_MAP_H