2 * lemon/bits/array_map.h - Part of LEMON, a generic C++ optimization library
4 * Copyright (C) 2006 Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport
5 * (Egervary Research Group on Combinatorial Optimization, EGRES).
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.
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
17 #ifndef LEMON_ARRAY_MAP_H
18 #define LEMON_ARRAY_MAP_H
21 #include <lemon/bits/map_extender.h>
22 #include <lemon/bits/alteration_notifier.h>
23 #include <lemon/concept_check.h>
24 #include <lemon/concept/maps.h>
26 /// \ingroup graphmapfactory
28 /// \brief Graph maps that construct and destruct
29 /// their elements dynamically.
33 /// \ingroup graphmapfactory
35 /// \brief Graph map based on the array storage.
37 /// The ArrayMap template class is graph map structure what
38 /// automatically updates the map when a key is added to or erased from
39 /// the map. This map uses the allocators to implement
40 /// the container functionality.
42 /// The template parameter is the AlterationNotifier that the maps
43 /// will belong to and the Value.
45 template <typename _Graph,
48 class ArrayMap : public AlterationNotifier<_Item>::ObserverBase {
52 /// The graph type of the maps.
54 /// The reference map tag.
55 typedef True ReferenceMapTag;
57 /// The key type of the maps.
59 /// The value type of the map.
61 /// The const reference type of the map.
62 typedef const _Value& ConstReference;
63 /// The reference type of the map.
64 typedef _Value& Reference;
66 typedef const Value ConstValue;
67 typedef Value* Pointer;
68 typedef const Value* ConstPointer;
70 typedef AlterationNotifier<_Item> Registry;
72 /// The MapBase of the Map which imlements the core regisitry function.
73 typedef typename Registry::ObserverBase Parent;
78 typedef std::allocator<Value> Allocator;
83 /// \brief Graph initialized map constructor.
85 /// Graph initialized map constructor.
86 ArrayMap(const Graph& _g) : graph(&_g) {
88 attach(_g.getNotifier(Item()));
90 for (graph->first(it); it != INVALID; graph->next(it)) {
91 int id = graph->id(it);;
92 allocator.construct(&(values[id]), Value());
96 /// \brief Constructor to use default value to initialize the map.
98 /// It constructs a map and initialize all of the the map.
99 ArrayMap(const Graph& _g, const Value& _v) : graph(&_g) {
101 attach(_g.getNotifier(_Item()));
103 for (graph->first(it); it != INVALID; graph->next(it)) {
104 int id = graph->id(it);;
105 allocator.construct(&(values[id]), _v);
109 /// \brief Constructor to copy a map of the same map type.
111 /// Constructor to copy a map of the same map type.
112 ArrayMap(const ArrayMap& copy) : Parent(), graph(copy.graph) {
113 if (copy.attached()) {
114 attach(*copy.getRegistry());
116 capacity = copy.capacity;
117 if (capacity == 0) return;
118 values = allocator.allocate(capacity);
120 for (graph->first(it); it != INVALID; graph->next(it)) {
121 int id = graph->id(it);;
122 allocator.construct(&(values[id]), copy.values[id]);
126 /// \brief The destructor of the map.
128 /// The destructor of the map.
129 virtual ~ArrayMap() {
138 ArrayMap& operator=(const ArrayMap&);
142 using Parent::attach;
143 using Parent::detach;
144 using Parent::attached;
146 const Graph* getGraph() {
153 /// \brief The subscript operator.
155 /// The subscript operator. The map can be subscripted by the
156 /// actual keys of the graph.
157 Value& operator[](const Key& key) {
158 int id = graph->id(key);
162 /// \brief The const subscript operator.
164 /// The const subscript operator. The map can be subscripted by the
165 /// actual keys of the graph.
166 const Value& operator[](const Key& key) const {
167 int id = graph->id(key);
171 /// \brief Setter function of the map.
173 /// Setter function of the map. Equivalent with map[key] = val.
174 /// This is a compatibility feature with the not dereferable maps.
175 void set(const Key& key, const Value& val) {
181 /// Add a new key to the map. It called by the map registry.
183 virtual void add(const Key& key) {
184 int id = graph->id(key);
185 if (id >= capacity) {
186 int new_capacity = (capacity == 0 ? 1 : capacity);
187 while (new_capacity <= id) {
190 Value* new_values = allocator.allocate(new_capacity);
192 for (graph->first(it); it != INVALID; graph->next(it)) {
193 int jd = graph->id(it);;
195 allocator.construct(&(new_values[jd]), values[jd]);
196 allocator.destroy(&(values[jd]));
199 if (capacity != 0) allocator.deallocate(values, capacity);
201 capacity = new_capacity;
203 allocator.construct(&(values[id]), Value());
206 virtual void add(const std::vector<Key>& keys) {
208 for (int i = 0; i < (int)keys.size(); ++i) {
209 int id = graph->id(keys[i]);
214 if (max_id >= capacity) {
215 int new_capacity = (capacity == 0 ? 1 : capacity);
216 while (new_capacity <= max_id) {
219 Value* new_values = allocator.allocate(new_capacity);
221 for (graph->first(it); it != INVALID; graph->next(it)) {
222 int id = graph->id(it);
224 for (int i = 0; i < (int)keys.size(); ++i) {
225 int jd = graph->id(keys[i]);
232 allocator.construct(&(new_values[id]), values[id]);
233 allocator.destroy(&(values[id]));
235 if (capacity != 0) allocator.deallocate(values, capacity);
237 capacity = new_capacity;
239 for (int i = 0; i < (int)keys.size(); ++i) {
240 int id = graph->id(keys[i]);
241 allocator.construct(&(values[id]), Value());
245 /// Erase a key from the map. It called by the map registry.
247 virtual void erase(const Key& key) {
248 int id = graph->id(key);
249 allocator.destroy(&(values[id]));
252 virtual void erase(const std::vector<Key>& keys) {
253 for (int i = 0; i < (int)keys.size(); ++i) {
254 int id = graph->id(keys[i]);
255 allocator.destroy(&(values[id]));
259 virtual void build() {
262 for (graph->first(it); it != INVALID; graph->next(it)) {
263 int id = graph->id(it);;
264 allocator.construct(&(values[id]), Value());
268 virtual void clear() {
271 for (graph->first(it); it != INVALID; graph->next(it)) {
272 int id = graph->id(it);
273 allocator.destroy(&(values[id]));
275 allocator.deallocate(values, capacity);
282 void allocate_memory() {
283 int max_id = graph->maxId(_Item());
290 while (capacity <= max_id) {
293 values = allocator.allocate(capacity);
305 #endif //LEMON_ARRAY_MAP_H