diff -r d8475431bbbb -r 8e85e6bbefdf lemon/bits/array_map.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/lemon/bits/array_map.h Mon May 23 04:48:14 2005 +0000 @@ -0,0 +1,369 @@ +/* -*- C++ -*- + * lemon/bits/array_map.h - Part of LEMON, a generic C++ optimization library + * + * Copyright (C) 2005 Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport + * (Egervary Research Group on Combinatorial Optimization, EGRES). + * + * Permission to use, modify and distribute this software is granted + * provided that this copyright notice appears in all copies. For + * precise terms see the accompanying LICENSE file. + * + * This software is provided "AS IS" with no warranty of any kind, + * express or implied, and with no claim as to its suitability for any + * purpose. + * + */ + +#ifndef LEMON_ARRAY_MAP_H +#define LEMON_ARRAY_MAP_H + +#include +#include + +///\ingroup graphmaps +///\file +///\brief Graph maps that construates and destruates +///their elements dynamically. + +namespace lemon { + + + /// \addtogroup graphmaps + /// @{ + + /// The ArrayMap template class is graph map structure what + /// automatically updates the map when a key is added to or erased from + /// the map. This map factory uses the allocators to implement + /// the container functionality. + /// + /// The template parameter is the AlterationNotifier that the maps + /// will belong to and the Value. + + + template + class ArrayMap : public AlterationNotifier<_Item>::ObserverBase { + + typedef _Item Item; + public: + + /// The graph type of the maps. + typedef _Graph Graph; + /// The key type of the maps. + typedef _Item Key; + + typedef AlterationNotifier<_Item> Registry; + + /// The MapBase of the Map which imlements the core regisitry function. + typedef typename Registry::ObserverBase Parent; + + /// The value type of the map. + typedef _Value Value; + + + private: + typedef std::allocator Allocator; + + + public: + + /// Graph and Registry initialized map constructor. + + ArrayMap(const Graph& _g) : graph(&_g) { + Item it; + attach(_g.getNotifier(Item())); + allocate_memory(); + for (graph->first(it); it != INVALID; graph->next(it)) { + int id = graph->id(it);; + allocator.construct(&(values[id]), Value()); + } + } + + /// Constructor to use default value to initialize the map. + + /// It constrates a map and initialize all of the the map. + + ArrayMap(const Graph& _g, const Value& _v) : graph(&_g) { + Item it; + attach(_g.getNotifier(_Item())); + allocate_memory(); + for (graph->first(it); it != INVALID; graph->next(it)) { + int id = graph->id(it);; + allocator.construct(&(values[id]), _v); + } + } + + /// Constructor to copy a map of the same map type. + + ArrayMap(const ArrayMap& copy) : Parent() { + if (copy.attached()) { + attach(*copy.getRegistry()); + } + capacity = copy.capacity; + if (capacity == 0) return; + values = allocator.allocate(capacity); + Item it; + for (graph->first(it); it != INVALID; graph->next(it)) { + int id = graph->id(it);; + allocator.construct(&(values[id]), copy.values[id]); + } + } + + using Parent::attach; + using Parent::detach; + using Parent::attached; + + /// Assign operator to copy a map of the same map type. + + ArrayMap& operator=(const ArrayMap& copy) { + if (© == this) return *this; + + if (graph != copy.graph) { + if (attached()) { + clear(); + detach(); + } + if (copy.attached()) { + attach(*copy.getRegistry()); + } + capacity = copy.capacity; + if (capacity == 0) return *this; + values = allocator.allocate(capacity); + } + + Item it; + for (graph->first(it); it != INVALID; graph->next(it)) { + int id = graph->id(it);; + allocator.construct(&(values[id]), copy.values[id]); + } + + return *this; + } + + /// The destructor of the map. + + virtual ~ArrayMap() { + if (attached()) { + clear(); + detach(); + } + } + + + ///The subscript operator. The map can be subscripted by the + ///actual keys of the graph. + + Value& operator[](const Key& key) { + int id = graph->id(key); + return values[id]; + } + + + ///The const subscript operator. The map can be subscripted by the + ///actual keys of the graph. + + const Value& operator[](const Key& key) const { + int id = graph->id(key); + return values[id]; + } + + /// Setter function of the map. Equivalent with map[key] = val. + /// This is a compatibility feature with the not dereferable maps. + + void set(const Key& key, const Value& val) { + (*this)[key] = val; + } + + /// Add a new key to the map. It called by the map registry. + + void add(const Key& key) { + int id = graph->id(key); + if (id >= capacity) { + int new_capacity = (capacity == 0 ? 1 : capacity); + while (new_capacity <= id) { + new_capacity <<= 1; + } + Value* new_values = allocator.allocate(new_capacity); + Item it; + for (graph->first(it); it != INVALID; graph->next(it)) { + int jd = graph->id(it);; + if (id != jd) { + allocator.construct(&(new_values[jd]), values[jd]); + allocator.destroy(&(values[jd])); + } + } + if (capacity != 0) allocator.deallocate(values, capacity); + values = new_values; + capacity = new_capacity; + } + allocator.construct(&(values[id]), Value()); + } + + void add(const std::vector& keys) { + int max_id = -1; + for (int i = 0; i < (int)keys.size(); ++i) { + int id = graph->id(keys[i]); + if (id > max_id) { + max_id = id; + } + } + if (max_id >= capacity) { + int new_capacity = (capacity == 0 ? 1 : capacity); + while (new_capacity <= max_id) { + new_capacity <<= 1; + } + Value* new_values = allocator.allocate(new_capacity); + Item it; + for (graph->first(it); it != INVALID; graph->next(it)) { + int id = graph->id(it); + bool found = false; + for (int i = 0; i < (int)keys.size(); ++i) { + int jd = graph->id(keys[i]); + if (id == jd) { + found = true; + break; + } + } + if (found) continue; + allocator.construct(&(new_values[id]), values[id]); + allocator.destroy(&(values[id])); + } + if (capacity != 0) allocator.deallocate(values, capacity); + values = new_values; + capacity = new_capacity; + } + for (int i = 0; i < (int)keys.size(); ++i) { + int id = graph->id(keys[i]); + allocator.construct(&(values[id]), Value()); + } + } + + /// Erase a key from the map. It called by the map registry. + + void erase(const Key& key) { + int id = graph->id(key); + allocator.destroy(&(values[id])); + } + + void erase(const std::vector& keys) { + for (int i = 0; i < (int)keys.size(); ++i) { + int id = graph->id(keys[i]); + allocator.destroy(&(values[id])); + } + } + + void build() { + allocate_memory(); + Item it; + for (graph->first(it); it != INVALID; graph->next(it)) { + int id = graph->id(it);; + allocator.construct(&(values[id]), Value()); + } + } + + void clear() { + if (capacity != 0) { + Item it; + for (graph->first(it); it != INVALID; graph->next(it)) { + int id = graph->id(it); + allocator.destroy(&(values[id])); + } + allocator.deallocate(values, capacity); + capacity = 0; + } + } + + const Graph* getGraph() { + return graph; + } + + private: + + void allocate_memory() { + int max_id = graph->maxId(_Item()); + if (max_id == -1) { + capacity = 0; + values = 0; + return; + } + capacity = 1; + while (capacity <= max_id) { + capacity <<= 1; + } + values = allocator.allocate(capacity); + } + + const Graph* graph; + int capacity; + Value* values; + Allocator allocator; + + }; + + template + class ArrayMappableGraphExtender : public _Base { + public: + + typedef ArrayMappableGraphExtender<_Base> Graph; + typedef _Base Parent; + + typedef typename Parent::Node Node; + typedef typename Parent::NodeIt NodeIt; + typedef typename Parent::NodeNotifier NodeObserverRegistry; + + typedef typename Parent::Edge Edge; + typedef typename Parent::EdgeIt EdgeIt; + typedef typename Parent::EdgeNotifier EdgeObserverRegistry; + + + + template + class NodeMap + : public IterableMapExtender > { + public: + typedef ArrayMappableGraphExtender<_Base> Graph; + + typedef typename Graph::Node Node; + typedef typename Graph::NodeIt NodeIt; + + typedef IterableMapExtender > Parent; + + //typedef typename Parent::Graph Graph; + typedef typename Parent::Value Value; + + NodeMap(const Graph& g) + : Parent(g) {} + NodeMap(const Graph& g, const Value& v) + : Parent(g, v) {} + + }; + + template + class EdgeMap + : public IterableMapExtender > { + public: + typedef ArrayMappableGraphExtender<_Base> Graph; + + typedef typename Graph::Edge Edge; + typedef typename Graph::EdgeIt EdgeIt; + + typedef IterableMapExtender > Parent; + + //typedef typename Parent::Graph Graph; + typedef typename Parent::Value Value; + + EdgeMap(const Graph& g) + : Parent(g) {} + EdgeMap(const Graph& g, const Value& v) + : Parent(g, v) {} + + }; + + }; + +/// @} + +} + +#endif //LEMON_ARRAY_MAP_H