gravatar
kpeter (Peter Kovacs)
kpeter@inf.elte.hu
Add a new build() function to StaticDigraph (#68) This function builds the digraph from an arc list that contains pairs of integer indices from the range [0..n-1]. It is useful in the cases when you would like to build a StaticDigraph from scratch, i.e. you do not want to build another digraph that can be copied using the other build() function.
0 2 0
default
2 files changed with 111 insertions and 0 deletions:
↑ Collapse diff ↑
Ignore white space 64 line context
... ...
@@ -168,64 +168,105 @@
168 168
      }
169 169

	
170 170
      ArcLess<Digraph, NodeRefMap> arcLess(digraph, nodeRef);
171 171

	
172 172
      int arc_index = 0;
173 173
      for (typename Digraph::NodeIt n(digraph); n != INVALID; ++n) {
174 174
        int source = nodeRef[n].id;
175 175
        std::vector<GArc> arcs;
176 176
        for (typename Digraph::OutArcIt e(digraph, n); e != INVALID; ++e) {
177 177
          arcs.push_back(e);
178 178
        }
179 179
        if (!arcs.empty()) {
180 180
          node_first_out[source] = arc_index;
181 181
          std::sort(arcs.begin(), arcs.end(), arcLess);
182 182
          for (typename std::vector<GArc>::iterator it = arcs.begin();
183 183
               it != arcs.end(); ++it) {
184 184
            int target = nodeRef[digraph.target(*it)].id;
185 185
            arcRef[*it] = Arc(arc_index);
186 186
            arc_source[arc_index] = source; 
187 187
            arc_target[arc_index] = target;
188 188
            arc_next_in[arc_index] = node_first_in[target];
189 189
            node_first_in[target] = arc_index;
190 190
            arc_next_out[arc_index] = arc_index + 1;
191 191
            ++arc_index;
192 192
          }
193 193
          arc_next_out[arc_index - 1] = -1;
194 194
        } else {
195 195
          node_first_out[source] = arc_index;
196 196
        }
197 197
      }
198 198
      node_first_out[node_num] = arc_num;
199 199
    }
200
    
201
    template <typename ArcListIterator>
202
    void build(int n, ArcListIterator first, ArcListIterator last) {
203
      built = true;
204

	
205
      node_num = n;
206
      arc_num = std::distance(first, last);
207

	
208
      node_first_out = new int[node_num + 1];
209
      node_first_in = new int[node_num];
210

	
211
      arc_source = new int[arc_num];
212
      arc_target = new int[arc_num];
213
      arc_next_out = new int[arc_num];
214
      arc_next_in = new int[arc_num];
215
      
216
      for (int i = 0; i != node_num; ++i) {
217
        node_first_in[i] = -1;
218
      }      
219
      
220
      int arc_index = 0;
221
      for (int i = 0; i != node_num; ++i) {
222
        node_first_out[i] = arc_index;
223
        for ( ; first != last && (*first).first == i; ++first) {
224
          int j = (*first).second;
225
          LEMON_ASSERT(j >= 0 && j < node_num,
226
            "Wrong arc list for StaticDigraph::build()");
227
          arc_source[arc_index] = i;
228
          arc_target[arc_index] = j;
229
          arc_next_in[arc_index] = node_first_in[j];
230
          node_first_in[j] = arc_index;
231
          arc_next_out[arc_index] = arc_index + 1;
232
          ++arc_index;
233
        }
234
        if (arc_index > node_first_out[i])
235
          arc_next_out[arc_index - 1] = -1;
236
      }
237
      LEMON_ASSERT(first == last,
238
        "Wrong arc list for StaticDigraph::build()");
239
      node_first_out[node_num] = arc_num;
240
    }
200 241

	
201 242
  protected:
202 243

	
203 244
    void fastFirstOut(Arc& e, const Node& n) const {
204 245
      e.id = node_first_out[n.id];
205 246
    }
206 247

	
207 248
    static void fastNextOut(Arc& e) {
208 249
      ++e.id;
209 250
    }
210 251
    void fastLastOut(Arc& e, const Node& n) const {
211 252
      e.id = node_first_out[n.id + 1];
212 253
    }
213 254

	
214 255
  protected:
215 256
    bool built;
216 257
    int node_num;
217 258
    int arc_num;
218 259
    int *node_first_out;
219 260
    int *node_first_in;
220 261
    int *arc_source;
221 262
    int *arc_target;
222 263
    int *arc_next_in;
223 264
    int *arc_next_out;
224 265
  };
225 266

	
226 267
  typedef DigraphExtender<StaticDigraphBase> ExtendedStaticDigraphBase;
227 268

	
228 269

	
229 270
  /// \ingroup graphs
230 271
  ///
231 272
  /// \brief A static directed graph class.
... ...
@@ -299,64 +340,102 @@
299 340
    int arcNum() const { return arc_num; }
300 341

	
301 342
    /// \brief Build the digraph copying another digraph.
302 343
    ///
303 344
    /// This function builds the digraph copying another digraph of any
304 345
    /// kind. It can be called more than once, but in such case, the whole
305 346
    /// structure and all maps will be cleared and rebuilt.
306 347
    ///
307 348
    /// This method also makes possible to copy a digraph to a StaticDigraph
308 349
    /// structure using \ref DigraphCopy.
309 350
    /// 
310 351
    /// \param digraph An existing digraph to be copied.
311 352
    /// \param nodeRef The node references will be copied into this map.
312 353
    /// Its key type must be \c Digraph::Node and its value type must be
313 354
    /// \c StaticDigraph::Node.
314 355
    /// It must conform to the \ref concepts::ReadWriteMap "ReadWriteMap"
315 356
    /// concept.
316 357
    /// \param arcRef The arc references will be copied into this map.
317 358
    /// Its key type must be \c Digraph::Arc and its value type must be
318 359
    /// \c StaticDigraph::Arc.
319 360
    /// It must conform to the \ref concepts::WriteMap "WriteMap" concept.
320 361
    ///
321 362
    /// \note If you do not need the arc references, then you could use
322 363
    /// \ref NullMap for the last parameter. However the node references
323 364
    /// are required by the function itself, thus they must be readable
324 365
    /// from the map.
325 366
    template <typename Digraph, typename NodeRefMap, typename ArcRefMap>
326 367
    void build(const Digraph& digraph, NodeRefMap& nodeRef, ArcRefMap& arcRef) {
327 368
      if (built) Parent::clear();
328 369
      Parent::build(digraph, nodeRef, arcRef);
329 370
    }
330 371
  
372
    /// \brief Build the digraph from an arc list.
373
    ///
374
    /// This function builds the digraph from the given arc list.
375
    /// It can be called more than once, but in such case, the whole
376
    /// structure and all maps will be cleared and rebuilt.
377
    ///
378
    /// The list of the arcs must be given in the range <tt>[begin, end)</tt>
379
    /// specified by STL compatible itartors whose \c value_type must be
380
    /// <tt>std::pair<int,int></tt>.
381
    /// Each arc must be specified by a pair of integer indices
382
    /// from the range <tt>[0..n-1]</tt>. <i>The pairs must be in a
383
    /// non-decreasing order with respect to their first values.</i>
384
    /// If the k-th pair in the list is <tt>(i,j)</tt>, then
385
    /// <tt>arc(k-1)</tt> will connect <tt>node(i)</tt> to <tt>node(j)</tt>.
386
    ///
387
    /// \param n The number of nodes.
388
    /// \param begin An iterator pointing to the beginning of the arc list.
389
    /// \param end An iterator pointing to the end of the arc list.
390
    ///
391
    /// For example, a simple digraph can be constructed like this.
392
    /// \code
393
    ///   std::vector<std::pair<int,int> > arcs;
394
    ///   arcs.push_back(std::make_pair(0,1));
395
    ///   arcs.push_back(std::make_pair(0,2));
396
    ///   arcs.push_back(std::make_pair(1,3));
397
    ///   arcs.push_back(std::make_pair(1,2));
398
    ///   arcs.push_back(std::make_pair(3,0));
399
    ///   StaticDigraph gr;
400
    ///   gr.build(4, arcs.begin(), arcs.end());
401
    /// \endcode
402
    template <typename ArcListIterator>
403
    void build(int n, ArcListIterator begin, ArcListIterator end) {
404
      if (built) Parent::clear();
405
      StaticDigraphBase::build(n, begin, end);
406
      notifier(Node()).build();
407
      notifier(Arc()).build();
408
    }
409

	
331 410
    /// \brief Clear the digraph.
332 411
    ///
333 412
    /// This function erases all nodes and arcs from the digraph.
334 413
    void clear() {
335 414
      Parent::clear();
336 415
    }
337 416

	
338 417
  protected:
339 418

	
340 419
    using Parent::fastFirstOut;
341 420
    using Parent::fastNextOut;
342 421
    using Parent::fastLastOut;
343 422
    
344 423
  public:
345 424

	
346 425
    class OutArcIt : public Arc {
347 426
    public:
348 427

	
349 428
      OutArcIt() { }
350 429

	
351 430
      OutArcIt(Invalid i) : Arc(i) { }
352 431

	
353 432
      OutArcIt(const StaticDigraph& digraph, const Node& node) {
354 433
	digraph.fastFirstOut(*this, node);
355 434
	digraph.fastLastOut(last, node);
356 435
        if (last == *this) *this = INVALID;
357 436
      }
358 437

	
359 438
      OutArcIt(const StaticDigraph& digraph, const Arc& arc) : Arc(arc) {
360 439
        if (arc != INVALID) {
361 440
          digraph.fastLastOut(last, digraph.source(arc));
362 441
        }
Ignore white space 6 line context
... ...
@@ -412,64 +412,96 @@
412 412
  checkGraphArcList(G, 1);
413 413

	
414 414
  checkGraphOutArcList(G, nref[n1], 1);
415 415
  checkGraphOutArcList(G, nref[n2], 0);
416 416
  checkGraphOutArcList(G, nref[n3], 0);
417 417

	
418 418
  checkGraphInArcList(G, nref[n1], 0);
419 419
  checkGraphInArcList(G, nref[n2], 1);
420 420
  checkGraphInArcList(G, nref[n3], 0);
421 421

	
422 422
  checkGraphConArcList(G, 1);
423 423

	
424 424
  SmartDigraph::Arc
425 425
    a2 = g.addArc(n2, n1),
426 426
    a3 = g.addArc(n2, n3),
427 427
    a4 = g.addArc(n2, n3);
428 428

	
429 429
  digraphCopy(g, G).nodeRef(nref).run();
430 430

	
431 431
  checkGraphNodeList(G, 3);
432 432
  checkGraphArcList(G, 4);
433 433

	
434 434
  checkGraphOutArcList(G, nref[n1], 1);
435 435
  checkGraphOutArcList(G, nref[n2], 3);
436 436
  checkGraphOutArcList(G, nref[n3], 0);
437 437

	
438 438
  checkGraphInArcList(G, nref[n1], 1);
439 439
  checkGraphInArcList(G, nref[n2], 1);
440 440
  checkGraphInArcList(G, nref[n3], 2);
441 441

	
442 442
  checkGraphConArcList(G, 4);
443 443

	
444
  std::vector<std::pair<int,int> > arcs;
445
  arcs.push_back(std::make_pair(0,1));
446
  arcs.push_back(std::make_pair(0,2));
447
  arcs.push_back(std::make_pair(1,3));
448
  arcs.push_back(std::make_pair(1,2));
449
  arcs.push_back(std::make_pair(3,0));
450
  arcs.push_back(std::make_pair(3,3));
451
  arcs.push_back(std::make_pair(4,2));
452
  arcs.push_back(std::make_pair(4,3));
453
  arcs.push_back(std::make_pair(4,1));
454

	
455
  G.build(6, arcs.begin(), arcs.end());
456
  
457
  checkGraphNodeList(G, 6);
458
  checkGraphArcList(G, 9);
459

	
460
  checkGraphOutArcList(G, G.node(0), 2);
461
  checkGraphOutArcList(G, G.node(1), 2);
462
  checkGraphOutArcList(G, G.node(2), 0);
463
  checkGraphOutArcList(G, G.node(3), 2);
464
  checkGraphOutArcList(G, G.node(4), 3);
465
  checkGraphOutArcList(G, G.node(5), 0);
466

	
467
  checkGraphInArcList(G, G.node(0), 1);
468
  checkGraphInArcList(G, G.node(1), 2);
469
  checkGraphInArcList(G, G.node(2), 3);
470
  checkGraphInArcList(G, G.node(3), 3);
471
  checkGraphInArcList(G, G.node(4), 0);
472
  checkGraphInArcList(G, G.node(5), 0);
473

	
474
  checkGraphConArcList(G, 9);
475

	
444 476
  checkNodeIds(G);
445 477
  checkArcIds(G);
446 478
  checkGraphNodeMap(G);
447 479
  checkGraphArcMap(G);
448 480
  
449 481
  int n = G.nodeNum();
450 482
  int m = G.arcNum();
451 483
  check(G.index(G.node(n-1)) == n-1, "Wrong index.");
452 484
  check(G.index(G.arc(m-1)) == m-1, "Wrong index.");
453 485
}
454 486

	
455 487
void checkFullDigraph(int num) {
456 488
  typedef FullDigraph Digraph;
457 489
  DIGRAPH_TYPEDEFS(Digraph);
458 490
  Digraph G(num);
459 491

	
460 492
  checkGraphNodeList(G, num);
461 493
  checkGraphArcList(G, num * num);
462 494

	
463 495
  for (NodeIt n(G); n != INVALID; ++n) {
464 496
    checkGraphOutArcList(G, n, num);
465 497
    checkGraphInArcList(G, n, num);
466 498
  }
467 499

	
468 500
  checkGraphConArcList(G, num * num);
469 501

	
470 502
  checkNodeIds(G);
471 503
  checkArcIds(G);
472 504
  checkGraphNodeMap(G);
473 505
  checkGraphArcMap(G);
474 506

	
475 507
  for (int i = 0; i < G.nodeNum(); ++i) {
0 comments (0 inline)