1 /** \file 2 * \brief Declaration and implementation of EdgeArray class. 3 * 4 * \author Carsten Gutwenger 5 * 6 * \par License: 7 * This file is part of the Open Graph Drawing Framework (OGDF). 8 * 9 * \par 10 * Copyright (C)<br> 11 * See README.md in the OGDF root directory for details. 12 * 13 * \par 14 * This program is free software; you can redistribute it and/or 15 * modify it under the terms of the GNU General Public License 16 * Version 2 or 3 as published by the Free Software Foundation; 17 * see the file LICENSE.txt included in the packaging of this file 18 * for details. 19 * 20 * \par 21 * This program is distributed in the hope that it will be useful, 22 * but WITHOUT ANY WARRANTY; without even the implied warranty of 23 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 24 * GNU General Public License for more details. 25 * 26 * \par 27 * You should have received a copy of the GNU General Public 28 * License along with this program; if not, see 29 * http://www.gnu.org/copyleft/gpl.html 30 */ 31 32 #pragma once 33 34 #include <ogdf/basic/Graph_d.h> 35 36 37 namespace ogdf { 38 39 40 //! Abstract base class for edge arrays. 41 /** 42 * Defines the interface for event handling used by the Graph class. 43 * Use the parameterized class EdgeArray for creating edge arrays. 44 */ 45 class EdgeArrayBase { 46 /** 47 * Pointer to list element in the list of all registered edge 48 * arrays which references this array. 49 */ 50 ListIterator<EdgeArrayBase*> m_it; 51 52 public: 53 const Graph *m_pGraph; //!< The associated graph. 54 55 //! Initializes an edge array not associated with a graph. EdgeArrayBase()56 EdgeArrayBase() : m_pGraph(nullptr) { } 57 58 //! Initializes an edge array associated with \p pG. EdgeArrayBase(const Graph * pG)59 explicit EdgeArrayBase(const Graph *pG) : m_pGraph(pG) { 60 if(pG) m_it = pG->registerArray(this); 61 } 62 63 //! Moves edge array \p base to this edge array. EdgeArrayBase(EdgeArrayBase & base)64 EdgeArrayBase(EdgeArrayBase &base) : m_it(base.m_it), m_pGraph(base.m_pGraph) { 65 if(m_pGraph) m_pGraph->moveRegisterArray(m_it, this); 66 base.m_pGraph = nullptr; 67 base.m_it = ListIterator<EdgeArrayBase*>(); 68 } 69 70 // destructor, unregisters the array ~EdgeArrayBase()71 virtual ~EdgeArrayBase() { 72 if (m_pGraph) m_pGraph->unregisterArray(m_it); 73 } 74 75 // event interface used by Graph 76 //! Virtual function called when table size has to be enlarged. 77 virtual void enlargeTable(int newTableSize) = 0; 78 //! Virtual function called when table has to be reinitialized. 79 virtual void reinit(int initTableSize) = 0; 80 //! Virtual function called when array is disconnected from the graph. 81 virtual void disconnect() = 0; 82 83 //! Associates the array with a new graph. reregister(const Graph * pG)84 void reregister(const Graph *pG) { 85 if (m_pGraph) m_pGraph->unregisterArray(m_it); 86 if ((m_pGraph = pG) != nullptr) m_it = pG->registerArray(this); 87 } 88 89 //! Moves array registration from \p base to this array. moveRegister(EdgeArrayBase & base)90 void moveRegister(EdgeArrayBase &base) { 91 if (m_pGraph) m_pGraph->unregisterArray(m_it); 92 m_pGraph = base.m_pGraph; 93 m_it = base.m_it; 94 base.m_pGraph = nullptr; 95 base.m_it = ListIterator<EdgeArrayBase*>(); 96 if (m_pGraph != nullptr) 97 m_pGraph->moveRegisterArray(m_it, this); 98 } 99 }; 100 101 //! Dynamic arrays indexed with edges. 102 /** 103 * @ingroup graph-containers 104 * 105 * Edge arrays represent a mapping from edges to data of type \a T. 106 * They adjust their table size automatically when the graph grows. 107 * 108 * @warn_undef_behavior_array 109 * 110 * @tparam T is the element type. 111 */ 112 template<class T> class EdgeArray : private Array<T>, protected EdgeArrayBase { 113 T m_x; //!< The default value for array elements. 114 115 public: 116 //! The type for array keys. 117 using key_type = edge; 118 //! The type for array entries. 119 using value_type = T; 120 121 //! The type for edge array iterators. 122 using iterator = internal::GraphArrayIterator<EdgeArray<T>>; 123 //! The type for edge array const iterators. 124 using const_iterator = internal::GraphArrayConstIterator<EdgeArray<T>>; 125 126 127 //! Constructs an empty edge array associated with no graph. EdgeArray()128 EdgeArray() : Array<T>(), EdgeArrayBase() { } 129 130 //! Constructs an edge array associated with \p G. EdgeArray(const Graph & G)131 explicit EdgeArray(const Graph &G) : Array<T>(G.edgeArrayTableSize()), EdgeArrayBase(&G) { } 132 133 //! Constructs an edge array associated with \p G. 134 /** 135 * @param G is the associated graph. 136 * @param x is the default value for all array elements. 137 */ EdgeArray(const Graph & G,const T & x)138 EdgeArray(const Graph &G, const T &x) : 139 Array<T>(0,G.edgeArrayTableSize()-1,x), EdgeArrayBase(&G), m_x(x) { } 140 141 //! Constructs an edge array that is a copy of \p A. 142 /** 143 * Associates the array with the same graph as \p A and copies all elements. 144 */ EdgeArray(const EdgeArray<T> & A)145 EdgeArray(const EdgeArray<T> &A) : Array<T>(A), EdgeArrayBase(A.m_pGraph), m_x(A.m_x) { } 146 147 //! Constructs an edge array containing the elements of \p A (move semantics). 148 /** 149 * Edge array \p A is empty afterwards and not associated with any graph. 150 */ EdgeArray(EdgeArray<T> && A)151 EdgeArray(EdgeArray<T> &&A) : Array<T>(std::move(A)), EdgeArrayBase(A), m_x(A.m_x) { } 152 153 154 /** 155 * @name Access methods 156 * These methods provide access to elements, size, and corresponding graph. 157 */ 158 //@{ 159 160 //! Returns true iff the array is associated with a graph. valid()161 bool valid() const { return Array<T>::low() <= Array<T>::high(); } 162 163 //! Returns a pointer to the associated graph. graphOf()164 const Graph *graphOf() const { 165 return m_pGraph; 166 } 167 168 //! Returns a reference to the element with index \p e. 169 const T &operator[](edge e) const { 170 OGDF_ASSERT(e != nullptr); 171 OGDF_ASSERT(e->graphOf() == m_pGraph); 172 return Array<T>::operator [](e->index()); 173 } 174 175 //! Returns a reference to the element with index \p e. 176 T &operator[](edge e) { 177 OGDF_ASSERT(e != nullptr); 178 OGDF_ASSERT(e->graphOf() == m_pGraph); 179 return Array<T>::operator [](e->index()); 180 } 181 182 //! Returns a reference to the element with index \p e. operator()183 const T &operator()(edge e) const { 184 OGDF_ASSERT(e != nullptr); 185 OGDF_ASSERT(e->graphOf() == m_pGraph); 186 return Array<T>::operator [](e->index()); 187 } 188 189 //! Returns a reference to the element with index \p e. operator()190 T &operator()(edge e) { 191 OGDF_ASSERT(e != nullptr); 192 OGDF_ASSERT(e->graphOf() == m_pGraph); 193 return Array<T>::operator [](e->index()); 194 } 195 196 //! Returns a reference to the element with index edge of \p adj. 197 const T &operator[](adjEntry adj) const { 198 OGDF_ASSERT(adj != nullptr); 199 return Array<T>::operator [](adj->index() >> 1); 200 } 201 202 //! Returns a reference to the element with index edge of \p adj. 203 T &operator[](adjEntry adj) { 204 OGDF_ASSERT(adj != nullptr); 205 return Array<T>::operator [](adj->index() >> 1); 206 } 207 208 //! Returns a reference to the element with index edge of \p adj. operator()209 const T &operator()(adjEntry adj) const { 210 OGDF_ASSERT(adj != nullptr); 211 return Array<T>::operator [](adj->index() >> 1); 212 } 213 214 //! Returns a reference to the element with index edge of \p adj. operator()215 T &operator()(adjEntry adj) { 216 OGDF_ASSERT(adj != nullptr); 217 return Array<T>::operator [](adj->index() >> 1); 218 } 219 220 //! Returns a reference to the element with index \p index. 221 //! \attention Make sure that \p index is a valid index for an edge in the associated graph! 222 OGDF_DEPRECATED("Edge arrays should be indexed by an edge, not an integer index.") 223 const T &operator[](int index) const 224 { return Array<T>::operator [](index); } 225 226 //! Returns a reference to the element with index \p index. 227 //! \attention Make sure that \p index is a valid index for an edge in the associated graph! 228 OGDF_DEPRECATED("Edge arrays should be indexed by an edge, not an integer index.") 229 T &operator[](int index) 230 { return Array<T>::operator [](index); } 231 232 //@} 233 /** 234 * @name Iterators 235 * These methods return bidirectional iterators to elements in the array. 236 */ 237 //@{ 238 239 //! Returns an iterator to the first entry in the edge array. 240 /** 241 * If the edge array is empty, a null pointer iterator is returned. 242 */ begin()243 iterator begin() { return iterator(m_pGraph->firstEdge(), this); } 244 245 //! Returns a const iterator to the first entry in the edge array. 246 /** 247 * If the edge array is empty, a null pointer iterator is returned. 248 */ begin()249 const_iterator begin() const { return const_iterator(m_pGraph->firstEdge(), this); } 250 251 //! Returns a const iterator to the first entry in the edge array. 252 /** 253 * If the edge array is empty, a null pointer iterator is returned. 254 */ cbegin()255 const_iterator cbegin() const { return const_iterator(m_pGraph->firstEdge(), this); } 256 257 //! Returns an iterator to one-past-last entry in the edge array. 258 /** 259 * This is always a null pointer iterator. 260 */ end()261 iterator end() { return iterator(nullptr, this); } 262 263 //! Returns a const iterator to one-past-last entry in the edge array. 264 /** 265 * This is always a null pointer iterator. 266 */ end()267 const_iterator end() const { return const_iterator(nullptr, this); } 268 269 //! Returns a const iterator to one-past-last entry in the edge array. 270 /** 271 * This is always a null pointer iterator. 272 */ cend()273 const_iterator cend() const { return const_iterator(nullptr, this); } 274 275 //@} 276 /** 277 * @name Initialization and assignment 278 * These methods can be used to reinitialize the array, or to initialize all elements with a given value. 279 */ 280 //@{ 281 282 //! Reinitializes the array. Associates the array with no graph. init()283 void init() { 284 Array<T>::init(); reregister(nullptr); 285 } 286 287 //! Reinitializes the array. Associates the array with \p G. init(const Graph & G)288 void init(const Graph &G) { 289 Array<T>::init(G.edgeArrayTableSize()); reregister(&G); 290 } 291 292 //! Reinitializes the array. Associates the array with \p G. 293 /** 294 * @param G is the associated graph. 295 * @param x is the default value. 296 */ init(const Graph & G,const T & x)297 void init(const Graph &G, const T &x) { 298 Array<T>::init(0,G.edgeArrayTableSize()-1, m_x = x); reregister(&G); 299 } 300 301 //! Sets all array elements to \p x. fill(const T & x)302 void fill(const T &x) { 303 int high = m_pGraph->maxEdgeIndex(); 304 if(high >= 0) 305 Array<T>::fill(0,high,x); 306 } 307 308 //! Assignment operator. 309 EdgeArray<T> &operator=(const EdgeArray<T> &a) { 310 Array<T>::operator=(a); 311 m_x = a.m_x; 312 reregister(a.m_pGraph); 313 return *this; 314 } 315 316 //! Assignment operator (move semantics). 317 /** 318 * Edge array \p a is empty afterwards and not associated with any graph. 319 */ 320 EdgeArray<T> &operator=(EdgeArray<T> &&a) { 321 Array<T>::operator=(std::move(a)); 322 m_x = a.m_x; 323 moveRegister(a); 324 return *this; 325 } 326 327 328 //@} 329 /** 330 * @name Helper functions 331 * These methods are mainly intended for internal use. 332 */ 333 //@{ 334 findSuccKey(key_type key)335 static key_type findSuccKey(key_type key) { return key->succ(); } findPredKey(key_type key)336 static key_type findPredKey(key_type key) { return key->pred(); } 337 338 //@} 339 340 private: enlargeTable(int newTableSize)341 virtual void enlargeTable(int newTableSize) { 342 Array<T>::resize(newTableSize,m_x); 343 } 344 reinit(int initTableSize)345 virtual void reinit(int initTableSize) { 346 Array<T>::init(0,initTableSize-1,m_x); 347 } 348 disconnect()349 virtual void disconnect() { 350 Array<T>::init(); 351 m_pGraph = nullptr; 352 } 353 354 OGDF_NEW_DELETE 355 }; 356 357 //! Bucket function for edges. 358 /** 359 * The bucket of an edge is stored in an edge array which is passed 360 * by the user at construction; only a pointer is stored to that array. 361 */ 362 class OGDF_EXPORT BucketEdgeArray : public BucketFunc<edge> 363 { 364 const EdgeArray<int> *m_pEdgeArray; //!< Pointer to edge array. 365 366 public: 367 //! Constructs a bucket function. 368 /** 369 * @param edgeArray contains the buckets for the edges. May not be deleted 370 * as long as the bucket function is used. 371 */ BucketEdgeArray(const EdgeArray<int> & edgeArray)372 explicit BucketEdgeArray(const EdgeArray<int> &edgeArray) : m_pEdgeArray(&edgeArray) { } 373 374 //! Returns bucket of edge \p e. getBucket(const edge & e)375 int getBucket(const edge &e) override { return (*m_pEdgeArray)[e]; } 376 }; 377 378 } 379