gravatar
kpeter (Peter Kovacs)
kpeter@inf.elte.hu
Much better implementation for node splitting (#311) in ListDigraph. This solution is the same as the one that is used in SmartDigraph. It is much faster and does not invalidate any iterator like the former implementation.
0 1 0
default
1 file changed with 9 insertions and 7 deletions:
↑ Collapse diff ↑
Ignore white space 192 line context
1 1
/* -*- mode: C++; indent-tabs-mode: nil; -*-
2 2
 *
3 3
 * This file is a part of LEMON, a generic C++ optimization library.
4 4
 *
5 5
 * Copyright (C) 2003-2009
6 6
 * Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport
7 7
 * (Egervary Research Group on Combinatorial Optimization, EGRES).
8 8
 *
9 9
 * Permission to use, modify and distribute this software is granted
10 10
 * provided that this copyright notice appears in all copies. For
11 11
 * precise terms see the accompanying LICENSE file.
12 12
 *
13 13
 * This software is provided "AS IS" with no warranty of any kind,
14 14
 * express or implied, and with no claim as to its suitability for any
15 15
 * purpose.
16 16
 *
17 17
 */
18 18

	
19 19
#ifndef LEMON_LIST_GRAPH_H
20 20
#define LEMON_LIST_GRAPH_H
21 21

	
22 22
///\ingroup graphs
23 23
///\file
24 24
///\brief ListDigraph and ListGraph classes.
25 25

	
26 26
#include <lemon/core.h>
27 27
#include <lemon/error.h>
28 28
#include <lemon/bits/graph_extender.h>
29 29

	
30 30
#include <vector>
31 31
#include <list>
32 32

	
33 33
namespace lemon {
34 34

	
35
  class ListDigraph;
36

	
35 37
  class ListDigraphBase {
36 38

	
37 39
  protected:
38 40
    struct NodeT {
39 41
      int first_in, first_out;
40 42
      int prev, next;
41 43
    };
42 44

	
43 45
    struct ArcT {
44 46
      int target, source;
45 47
      int prev_in, prev_out;
46 48
      int next_in, next_out;
47 49
    };
48 50

	
49 51
    std::vector<NodeT> nodes;
50 52

	
51 53
    int first_node;
52 54

	
53 55
    int first_free_node;
54 56

	
55 57
    std::vector<ArcT> arcs;
56 58

	
57 59
    int first_free_arc;
58 60

	
59 61
  public:
60 62

	
61 63
    typedef ListDigraphBase Digraph;
62 64

	
63 65
    class Node {
64 66
      friend class ListDigraphBase;
67
      friend class ListDigraph;
65 68
    protected:
66 69

	
67 70
      int id;
68 71
      explicit Node(int pid) { id = pid;}
69 72

	
70 73
    public:
71 74
      Node() {}
72 75
      Node (Invalid) { id = -1; }
73 76
      bool operator==(const Node& node) const {return id == node.id;}
74 77
      bool operator!=(const Node& node) const {return id != node.id;}
75 78
      bool operator<(const Node& node) const {return id < node.id;}
76 79
    };
77 80

	
78 81
    class Arc {
79 82
      friend class ListDigraphBase;
83
      friend class ListDigraph;
80 84
    protected:
81 85

	
82 86
      int id;
83 87
      explicit Arc(int pid) { id = pid;}
84 88

	
85 89
    public:
86 90
      Arc() {}
87 91
      Arc (Invalid) { id = -1; }
88 92
      bool operator==(const Arc& arc) const {return id == arc.id;}
89 93
      bool operator!=(const Arc& arc) const {return id != arc.id;}
90 94
      bool operator<(const Arc& arc) const {return id < arc.id;}
91 95
    };
92 96

	
93 97

	
94 98

	
95 99
    ListDigraphBase()
96 100
      : nodes(), first_node(-1),
97 101
        first_free_node(-1), arcs(), first_free_arc(-1) {}
98 102

	
99 103

	
100 104
    int maxNodeId() const { return nodes.size()-1; }
101 105
    int maxArcId() const { return arcs.size()-1; }
102 106

	
103 107
    Node source(Arc e) const { return Node(arcs[e.id].source); }
104 108
    Node target(Arc e) const { return Node(arcs[e.id].target); }
105 109

	
106 110

	
107 111
    void first(Node& node) const {
108 112
      node.id = first_node;
109 113
    }
110 114

	
111 115
    void next(Node& node) const {
112 116
      node.id = nodes[node.id].next;
113 117
    }
114 118

	
115 119

	
116 120
    void first(Arc& arc) const {
117 121
      int n;
118 122
      for(n = first_node;
119 123
          n!=-1 && nodes[n].first_in == -1;
120 124
          n = nodes[n].next) {}
121 125
      arc.id = (n == -1) ? -1 : nodes[n].first_in;
122 126
    }
123 127

	
124 128
    void next(Arc& arc) const {
125 129
      if (arcs[arc.id].next_in != -1) {
126 130
        arc.id = arcs[arc.id].next_in;
127 131
      } else {
128 132
        int n;
129 133
        for(n = nodes[arcs[arc.id].target].next;
130 134
            n!=-1 && nodes[n].first_in == -1;
131 135
            n = nodes[n].next) {}
132 136
        arc.id = (n == -1) ? -1 : nodes[n].first_in;
133 137
      }
134 138
    }
135 139

	
136 140
    void firstOut(Arc &e, const Node& v) const {
137 141
      e.id = nodes[v.id].first_out;
138 142
    }
139 143
    void nextOut(Arc &e) const {
140 144
      e.id=arcs[e.id].next_out;
141 145
    }
142 146

	
143 147
    void firstIn(Arc &e, const Node& v) const {
144 148
      e.id = nodes[v.id].first_in;
145 149
    }
146 150
    void nextIn(Arc &e) const {
147 151
      e.id=arcs[e.id].next_in;
148 152
    }
149 153

	
150 154

	
151 155
    static int id(Node v) { return v.id; }
152 156
    static int id(Arc e) { return e.id; }
153 157

	
154 158
    static Node nodeFromId(int id) { return Node(id);}
155 159
    static Arc arcFromId(int id) { return Arc(id);}
156 160

	
157 161
    bool valid(Node n) const {
158 162
      return n.id >= 0 && n.id < static_cast<int>(nodes.size()) &&
159 163
        nodes[n.id].prev != -2;
160 164
    }
161 165

	
162 166
    bool valid(Arc a) const {
163 167
      return a.id >= 0 && a.id < static_cast<int>(arcs.size()) &&
164 168
        arcs[a.id].prev_in != -2;
165 169
    }
166 170

	
167 171
    Node addNode() {
168 172
      int n;
169 173

	
170 174
      if(first_free_node==-1) {
171 175
        n = nodes.size();
172 176
        nodes.push_back(NodeT());
173 177
      } else {
174 178
        n = first_free_node;
175 179
        first_free_node = nodes[n].next;
... ...
@@ -374,204 +378,202 @@
374 378
    bool valid(Node n) const { return Parent::valid(n); }
375 379

	
376 380
    /// Arc validity check
377 381

	
378 382
    /// This function gives back \c true if the given arc is valid,
379 383
    /// i.e. it is a real arc of the digraph.
380 384
    ///
381 385
    /// \warning A removed arc could become valid again if new arcs are
382 386
    /// added to the digraph.
383 387
    bool valid(Arc a) const { return Parent::valid(a); }
384 388

	
385 389
    /// Change the target node of an arc
386 390

	
387 391
    /// This function changes the target node of the given arc \c a to \c n.
388 392
    ///
389 393
    ///\note \c ArcIt and \c OutArcIt iterators referencing the changed
390 394
    ///arc remain valid, however \c InArcIt iterators are invalidated.
391 395
    ///
392 396
    ///\warning This functionality cannot be used together with the Snapshot
393 397
    ///feature.
394 398
    void changeTarget(Arc a, Node n) {
395 399
      Parent::changeTarget(a,n);
396 400
    }
397 401
    /// Change the source node of an arc
398 402

	
399 403
    /// This function changes the source node of the given arc \c a to \c n.
400 404
    ///
401 405
    ///\note \c InArcIt iterators referencing the changed arc remain
402 406
    ///valid, however \c ArcIt and \c OutArcIt iterators are invalidated.
403 407
    ///
404 408
    ///\warning This functionality cannot be used together with the Snapshot
405 409
    ///feature.
406 410
    void changeSource(Arc a, Node n) {
407 411
      Parent::changeSource(a,n);
408 412
    }
409 413

	
410 414
    /// Reverse the direction of an arc.
411 415

	
412 416
    /// This function reverses the direction of the given arc.
413 417
    ///\note \c ArcIt, \c OutArcIt and \c InArcIt iterators referencing
414 418
    ///the changed arc are invalidated.
415 419
    ///
416 420
    ///\warning This functionality cannot be used together with the Snapshot
417 421
    ///feature.
418 422
    void reverseArc(Arc a) {
419 423
      Node t=target(a);
420 424
      changeTarget(a,source(a));
421 425
      changeSource(a,t);
422 426
    }
423 427

	
424 428
    ///Contract two nodes.
425 429

	
426 430
    ///This function contracts the given two nodes.
427 431
    ///Node \c v is removed, but instead of deleting its
428 432
    ///incident arcs, they are joined to node \c u.
429 433
    ///If the last parameter \c r is \c true (this is the default value),
430 434
    ///then the newly created loops are removed.
431 435
    ///
432 436
    ///\note The moved arcs are joined to node \c u using changeSource()
433 437
    ///or changeTarget(), thus \c ArcIt and \c OutArcIt iterators are
434 438
    ///invalidated for the outgoing arcs of node \c v and \c InArcIt
435 439
    ///iterators are invalidated for the incomming arcs of \c v.
436 440
    ///Moreover all iterators referencing node \c v or the removed 
437 441
    ///loops are also invalidated. Other iterators remain valid.
438 442
    ///
439 443
    ///\warning This functionality cannot be used together with the Snapshot
440 444
    ///feature.
441 445
    void contract(Node u, Node v, bool r = true)
442 446
    {
443 447
      for(OutArcIt e(*this,v);e!=INVALID;) {
444 448
        OutArcIt f=e;
445 449
        ++f;
446 450
        if(r && target(e)==u) erase(e);
447 451
        else changeSource(e,u);
448 452
        e=f;
449 453
      }
450 454
      for(InArcIt e(*this,v);e!=INVALID;) {
451 455
        InArcIt f=e;
452 456
        ++f;
453 457
        if(r && source(e)==u) erase(e);
454 458
        else changeTarget(e,u);
455 459
        e=f;
456 460
      }
457 461
      erase(v);
458 462
    }
459 463

	
460 464
    ///Split a node.
461 465

	
462 466
    ///This function splits the given node. First, a new node is added
463 467
    ///to the digraph, then the source of each outgoing arc of node \c n
464 468
    ///is moved to this new node.
465 469
    ///If the second parameter \c connect is \c true (this is the default
466 470
    ///value), then a new arc from node \c n to the newly created node
467 471
    ///is also added.
468 472
    ///\return The newly created node.
469 473
    ///
470
    ///\note \c ArcIt and \c OutArcIt iterators referencing the outgoing
471
    ///arcs of node \c n are invalidated. Other iterators remain valid.
474
    ///\note All iterators remain valid.
472 475
    ///
473 476
    ///\warning This functionality cannot be used together with the
474 477
    ///Snapshot feature.
475 478
    Node split(Node n, bool connect = true) {
476 479
      Node b = addNode();
477
      for(OutArcIt e(*this,n);e!=INVALID;) {
478
        OutArcIt f=e;
479
        ++f;
480
        changeSource(e,b);
481
        e=f;
480
      nodes[b.id].first_out=nodes[n.id].first_out;
481
      nodes[n.id].first_out=-1;
482
      for(int i=nodes[b.id].first_out; i!=-1; i=arcs[i].next_out) {
483
        arcs[i].source=b.id;
482 484
      }
483 485
      if (connect) addArc(n,b);
484 486
      return b;
485 487
    }
486 488

	
487 489
    ///Split an arc.
488 490

	
489 491
    ///This function splits the given arc. First, a new node \c v is
490 492
    ///added to the digraph, then the target node of the original arc
491 493
    ///is set to \c v. Finally, an arc from \c v to the original target
492 494
    ///is added.
493 495
    ///\return The newly created node.
494 496
    ///
495 497
    ///\note \c InArcIt iterators referencing the original arc are
496 498
    ///invalidated. Other iterators remain valid.
497 499
    ///
498 500
    ///\warning This functionality cannot be used together with the
499 501
    ///Snapshot feature.
500 502
    Node split(Arc a) {
501 503
      Node v = addNode();
502 504
      addArc(v,target(a));
503 505
      changeTarget(a,v);
504 506
      return v;
505 507
    }
506 508

	
507 509
    ///Clear the digraph.
508 510

	
509 511
    ///This function erases all nodes and arcs from the digraph.
510 512
    ///
511 513
    void clear() {
512 514
      Parent::clear();
513 515
    }
514 516

	
515 517
    /// Reserve memory for nodes.
516 518

	
517 519
    /// Using this function, it is possible to avoid superfluous memory
518 520
    /// allocation: if you know that the digraph you want to build will
519 521
    /// be large (e.g. it will contain millions of nodes and/or arcs),
520 522
    /// then it is worth reserving space for this amount before starting
521 523
    /// to build the digraph.
522 524
    /// \sa reserveArc()
523 525
    void reserveNode(int n) { nodes.reserve(n); };
524 526

	
525 527
    /// Reserve memory for arcs.
526 528

	
527 529
    /// Using this function, it is possible to avoid superfluous memory
528 530
    /// allocation: if you know that the digraph you want to build will
529 531
    /// be large (e.g. it will contain millions of nodes and/or arcs),
530 532
    /// then it is worth reserving space for this amount before starting
531 533
    /// to build the digraph.
532 534
    /// \sa reserveNode()
533 535
    void reserveArc(int m) { arcs.reserve(m); };
534 536

	
535 537
    /// \brief Class to make a snapshot of the digraph and restore
536 538
    /// it later.
537 539
    ///
538 540
    /// Class to make a snapshot of the digraph and restore it later.
539 541
    ///
540 542
    /// The newly added nodes and arcs can be removed using the
541 543
    /// restore() function.
542 544
    ///
543 545
    /// \note After a state is restored, you cannot restore a later state, 
544 546
    /// i.e. you cannot add the removed nodes and arcs again using
545 547
    /// another Snapshot instance.
546 548
    ///
547 549
    /// \warning Node and arc deletions and other modifications (e.g.
548 550
    /// reversing, contracting, splitting arcs or nodes) cannot be
549 551
    /// restored. These events invalidate the snapshot.
550 552
    /// However the arcs and nodes that were added to the digraph after
551 553
    /// making the current snapshot can be removed without invalidating it.
552 554
    class Snapshot {
553 555
    protected:
554 556

	
555 557
      typedef Parent::NodeNotifier NodeNotifier;
556 558

	
557 559
      class NodeObserverProxy : public NodeNotifier::ObserverBase {
558 560
      public:
559 561

	
560 562
        NodeObserverProxy(Snapshot& _snapshot)
561 563
          : snapshot(_snapshot) {}
562 564

	
563 565
        using NodeNotifier::ObserverBase::attach;
564 566
        using NodeNotifier::ObserverBase::detach;
565 567
        using NodeNotifier::ObserverBase::attached;
566 568

	
567 569
      protected:
568 570

	
569 571
        virtual void add(const Node& node) {
570 572
          snapshot.addNode(node);
571 573
        }
572 574
        virtual void add(const std::vector<Node>& nodes) {
573 575
          for (int i = nodes.size() - 1; i >= 0; ++i) {
574 576
            snapshot.addNode(nodes[i]);
575 577
          }
576 578
        }
577 579
        virtual void erase(const Node& node) {
0 comments (0 inline)