src/work/marci/oldies/list_graph.hh
author marci
Sat, 16 Oct 2004 00:20:13 +0000
changeset 944 4f064aff855e
permissions -rw-r--r--
It's time to design an iterable generic bfs
marci@280
     1
#ifndef LIST_GRAPH_HH
marci@280
     2
#define LIST_GRAPH_HH
marci@280
     3
marci@280
     4
#include <iostream>
marci@280
     5
#include <vector>
marci@280
     6
marci@280
     7
namespace hugo {
marci@280
     8
marci@280
     9
  template <typename It>
marci@280
    10
  int count(It it) { 
marci@280
    11
    int i=0;
marci@280
    12
    for( ; it.valid(); ++it) { ++i; } 
marci@280
    13
    return i;
marci@280
    14
  }
marci@280
    15
marci@280
    16
  class ListGraph {
marci@280
    17
marci@280
    18
    class node_item;
marci@280
    19
    class edge_item;
marci@280
    20
marci@280
    21
  public:
marci@280
    22
marci@280
    23
    class NodeIt;
marci@280
    24
    class EachNodeIt;
marci@280
    25
    class EdgeIt;
marci@280
    26
    class EachEdgeIt;
marci@280
    27
    class OutEdgeIt;
marci@280
    28
    class InEdgeIt;
marci@280
    29
    class SymEdgeIt;
marci@280
    30
    template <typename T> class NodeMap;
marci@280
    31
    template <typename T> class EdgeMap;
marci@280
    32
    
marci@280
    33
  private:
marci@280
    34
    
marci@280
    35
    template <typename T> friend class NodeMap;
marci@280
    36
    template <typename T> friend class EdgeMap;
marci@280
    37
marci@280
    38
    template <typename T>
marci@280
    39
    class NodeMap {
marci@280
    40
      const ListGraph& G; 
marci@280
    41
      std::vector<T> container;
marci@280
    42
    public:
marci@280
    43
      typedef T ValueType;
marci@280
    44
      typedef NodeIt KeyType;
marci@280
    45
      NodeMap(const ListGraph& _G) : G(_G), container(G.node_id) { }
marci@280
    46
      NodeMap(const ListGraph& _G, T a) : 
marci@280
    47
	G(_G), container(G.node_id, a) { }
marci@280
    48
      void set(NodeIt n, T a) { container[/*G.id(n)*/n.node->id]=a; }
marci@280
    49
      T get(NodeIt n) const { return container[/*G.id(n)*/n.node->id]; }
marci@280
    50
      T& operator[](NodeIt n) { return container[/*G.id(n)*/n.node->id]; }
marci@280
    51
      const T& operator[](NodeIt n) const { return container[/*G.id(n)*/n.node->id]; }
marci@280
    52
      void update() { container.resize(G.node_id); }
marci@280
    53
      void update(T a) { container.resize(G.node_id, a); }
marci@280
    54
    };
marci@280
    55
marci@280
    56
    template <typename T>
marci@280
    57
    class EdgeMap {
marci@280
    58
      const ListGraph& G; 
marci@280
    59
      std::vector<T> container;
marci@280
    60
    public:
marci@280
    61
      typedef T ValueType;
marci@280
    62
      typedef EdgeIt KeyType;
marci@280
    63
      EdgeMap(const ListGraph& _G) : G(_G), container(G.edge_id) { }
marci@280
    64
      EdgeMap(const ListGraph& _G, T a) : 
marci@280
    65
	G(_G), container(G.edge_id, a) { }
marci@280
    66
      void set(EdgeIt e, T a) { container[/*G.id(e)*/e.edge->id]=a; }
marci@280
    67
      T get(EdgeIt e) const { return container[/*G.id(e)*/e.edge->id]; }
marci@280
    68
      T& operator[](EdgeIt e) { return container[/*G.id(e)*/e.edge->id]; } 
marci@280
    69
      const T& operator[](EdgeIt e) const { return container[/*G.id(e)*/e.edge->id]; } 
marci@280
    70
      void update() { container.resize(G.edge_id); }
marci@280
    71
      void update(T a) { container.resize(G.edge_id, a); }
marci@280
    72
    };
marci@280
    73
marci@280
    74
    int node_id;
marci@280
    75
    int edge_id;
marci@280
    76
    int _node_num;
marci@280
    77
    int _edge_num;
marci@280
    78
marci@280
    79
    node_item* _first_node;
marci@280
    80
    node_item* _last_node;
marci@280
    81
marci@280
    82
    class node_item {
marci@280
    83
      friend class ListGraph;
marci@280
    84
      template <typename T> friend class NodeMap;
marci@280
    85
      
marci@280
    86
      friend class NodeIt;
marci@280
    87
      friend class EachNodeIt;
marci@280
    88
      friend class EdgeIt;
marci@280
    89
      friend class EachEdgeIt;
marci@280
    90
      friend class OutEdgeIt;
marci@280
    91
      friend class InEdgeIt;
marci@280
    92
      friend class SymEdgeIt;
marci@280
    93
      friend std::ostream& operator<<(std::ostream& os, const NodeIt& i);
marci@280
    94
      friend std::ostream& operator<<(std::ostream& os, const EdgeIt& i);
marci@280
    95
      //ListGraph* G;
marci@280
    96
      int id;
marci@280
    97
      edge_item* _first_out_edge;
marci@280
    98
      edge_item* _last_out_edge;
marci@280
    99
      edge_item* _first_in_edge;
marci@280
   100
      edge_item* _last_in_edge;
marci@280
   101
      node_item* _next_node;
marci@280
   102
      node_item* _prev_node;
marci@280
   103
    public:
marci@280
   104
      node_item() { }
marci@280
   105
    };
marci@280
   106
marci@280
   107
    class edge_item {
marci@280
   108
      friend class ListGraph;
marci@280
   109
      template <typename T> friend class EdgeMap;
marci@280
   110
marci@280
   111
      friend class NodeIt;
marci@280
   112
      friend class EachNodeIt;
marci@280
   113
      friend class EdgeIt;
marci@280
   114
      friend class EachEdgeIt;
marci@280
   115
      friend class OutEdgeIt;
marci@280
   116
      friend class InEdgeIt;
marci@280
   117
      friend class SymEdgeIt;
marci@280
   118
      friend std::ostream& operator<<(std::ostream& os, const EdgeIt& i);
marci@280
   119
      //ListGraph* G;
marci@280
   120
      int id;
marci@280
   121
      node_item* _tail;
marci@280
   122
      node_item* _head;
marci@280
   123
      edge_item* _next_out;
marci@280
   124
      edge_item* _prev_out;
marci@280
   125
      edge_item* _next_in;
marci@280
   126
      edge_item* _prev_in;
marci@280
   127
    public:
marci@280
   128
      edge_item() { }
marci@280
   129
    };
marci@280
   130
marci@280
   131
    node_item* _add_node() { 
marci@280
   132
      node_item* p=new node_item;
marci@280
   133
      p->id=node_id++;
marci@280
   134
      p->_first_out_edge=0;
marci@280
   135
      p->_last_out_edge=0;
marci@280
   136
      p->_first_in_edge=0;
marci@280
   137
      p->_last_in_edge=0;
marci@280
   138
      p->_prev_node=_last_node;
marci@280
   139
      p->_next_node=0;
marci@280
   140
      if (_last_node) _last_node->_next_node=p;
marci@280
   141
      _last_node=p;
marci@280
   142
      if (!_first_node) _first_node=p;
marci@280
   143
marci@280
   144
      ++_node_num;
marci@280
   145
      return p;
marci@280
   146
    }
marci@280
   147
marci@280
   148
    edge_item* _add_edge(node_item* _tail, node_item* _head) {
marci@280
   149
      edge_item* e=new edge_item;
marci@280
   150
      e->id=edge_id++;
marci@280
   151
      e->_tail=_tail;
marci@280
   152
      e->_head=_head;
marci@280
   153
      
marci@280
   154
      e->_prev_out=_tail->_last_out_edge;
marci@280
   155
      if (_tail->_last_out_edge) (_tail->_last_out_edge)->_next_out=e;
marci@280
   156
      _tail->_last_out_edge=e;
marci@280
   157
      if (!_tail->_first_out_edge) _tail->_first_out_edge=e; 
marci@280
   158
      e->_next_out=0;
marci@280
   159
 
marci@280
   160
      e->_prev_in=_head->_last_in_edge;
marci@280
   161
      if (_head->_last_in_edge) (_head->_last_in_edge)->_next_in=e;
marci@280
   162
      _head->_last_in_edge=e;
marci@280
   163
      if (!_head->_first_in_edge) { _head->_first_in_edge=e; } 
marci@280
   164
      e->_next_in=0;
marci@280
   165
marci@280
   166
      ++_edge_num;
marci@280
   167
      return e;
marci@280
   168
    }
marci@280
   169
marci@280
   170
    //deletes a node which has no out edge and no in edge
marci@280
   171
    void _delete_node(node_item* v) {
marci@280
   172
      if (v->_next_node) (v->_next_node)->_prev_node=v->_prev_node; else 
marci@280
   173
	_last_node=v->_prev_node;
marci@280
   174
      if (v->_prev_node) (v->_prev_node)->_next_node=v->_next_node; else 
marci@280
   175
	_first_node=v->_next_node;
marci@280
   176
marci@280
   177
      delete v;
marci@280
   178
      --_node_num;
marci@280
   179
    }
marci@280
   180
marci@280
   181
    void _delete_edge(edge_item* e) {
marci@280
   182
      if (e->_next_out) (e->_next_out)->_prev_out=e->_prev_out; else 
marci@280
   183
	(e->_tail)->_last_out_edge=e->_prev_out;
marci@280
   184
      if (e->_prev_out) (e->_prev_out)->_next_out=e->_next_out; else 
marci@280
   185
	(e->_tail)->_first_out_edge=e->_next_out;
marci@280
   186
      if (e->_next_in) (e->_next_in)->_prev_in=e->_prev_in; else 
marci@280
   187
	(e->_head)->_last_in_edge=e->_prev_in;
marci@280
   188
      if (e->_prev_in) (e->_prev_in)->_next_in=e->_next_in; else 
marci@280
   189
	(e->_head)->_first_in_edge=e->_next_in;
marci@280
   190
marci@280
   191
      delete e;
marci@280
   192
      --_edge_num;
marci@280
   193
    }
marci@280
   194
marci@280
   195
    void _set_tail(edge_item* e, node_item* _tail) {
marci@280
   196
      if (e->_next_out) (e->_next_out)->_prev_out=e->_prev_out; else 
marci@280
   197
	(e->_tail)->_last_out_edge=e->_prev_out;
marci@280
   198
      if (e->_prev_out) (e->_prev_out)->_next_out=e->_next_out; else 
marci@280
   199
	(e->_tail)->_first_out_edge=e->_next_out;
marci@280
   200
      
marci@280
   201
      e->_tail=_tail;
marci@280
   202
      
marci@280
   203
      e->_prev_out=_tail->_last_out_edge;
marci@280
   204
      if (_tail->_last_out_edge) (_tail->_last_out_edge)->_next_out=e;
marci@280
   205
      _tail->_last_out_edge=e;
marci@280
   206
      if (!_tail->_first_out_edge) _tail->_first_out_edge=e; 
marci@280
   207
      e->_next_out=0;
marci@280
   208
    }
marci@280
   209
marci@280
   210
    void _set_head(edge_item* e, node_item* _head) {
marci@280
   211
      if (e->_next_in) (e->_next_in)->_prev_in=e->_prev_in; else 
marci@280
   212
	(e->_head)->_last_in_edge=e->_prev_in;
marci@280
   213
      if (e->_prev_in) (e->_prev_in)->_next_in=e->_next_in; else 
marci@280
   214
	(e->_head)->_first_in_edge=e->_next_in;
marci@280
   215
      
marci@280
   216
      e->_head=_head;
marci@280
   217
      
marci@280
   218
      e->_prev_in=_head->_last_in_edge;
marci@280
   219
      if (_head->_last_in_edge) (_head->_last_in_edge)->_next_in=e;
marci@280
   220
      _head->_last_in_edge=e;
marci@280
   221
      if (!_head->_first_in_edge) { _head->_first_in_edge=e; } 
marci@280
   222
      e->_next_in=0;
marci@280
   223
    }
marci@280
   224
marci@280
   225
  public:
marci@280
   226
marci@280
   227
    /* default constructor */
marci@280
   228
marci@280
   229
    ListGraph() : node_id(0), edge_id(0), _node_num(0), _edge_num(0), _first_node(0), _last_node(0) { }
marci@280
   230
    
marci@280
   231
    ~ListGraph() { 
marci@280
   232
      while (first<EachNodeIt>().valid()) erase(first<EachNodeIt>());
marci@280
   233
    }
marci@280
   234
marci@280
   235
    int nodeNum() const { return _node_num; }
marci@280
   236
    int edgeNum() const { return _edge_num; }
marci@280
   237
marci@280
   238
    /* functions to construct iterators from the graph, or from each other */
marci@280
   239
marci@280
   240
    //EachNodeIt firstNode() const { return EachNodeIt(*this); }
marci@280
   241
    //EachEdgeIt firstEdge() const { return EachEdgeIt(*this); }
marci@280
   242
    
marci@280
   243
    //OutEdgeIt firstOutEdge(const NodeIt v) const { return OutEdgeIt(v); }
marci@280
   244
    //InEdgeIt firstInEdge(const NodeIt v) const { return InEdgeIt(v); }
marci@280
   245
    //SymEdgeIt firstSymEdge(const NodeIt v) const { return SymEdgeIt(v); }
marci@280
   246
    NodeIt tail(EdgeIt e) const { return e.tailNode(); }
marci@280
   247
    NodeIt head(EdgeIt e) const { return e.headNode(); }
marci@280
   248
marci@280
   249
    NodeIt aNode(const OutEdgeIt& e) const { return e.aNode(); }
marci@280
   250
    NodeIt aNode(const InEdgeIt& e) const { return e.aNode(); }
marci@280
   251
    NodeIt aNode(const SymEdgeIt& e) const { return e.aNode(); }
marci@280
   252
marci@280
   253
    NodeIt bNode(const OutEdgeIt& e) const { return e.bNode(); }
marci@280
   254
    NodeIt bNode(const InEdgeIt& e) const { return e.bNode(); }
marci@280
   255
    NodeIt bNode(const SymEdgeIt& e) const { return e.bNode(); }
marci@280
   256
marci@280
   257
    //NodeIt invalid_node() { return NodeIt(); }
marci@280
   258
    //EdgeIt invalid_edge() { return EdgeIt(); }
marci@280
   259
    //OutEdgeIt invalid_out_edge() { return OutEdgeIt(); }
marci@280
   260
    //InEdgeIt invalid_in_edge() { return InEdgeIt(); }
marci@280
   261
    //SymEdgeIt invalid_sym_edge() { return SymEdgeIt(); }
marci@280
   262
marci@280
   263
    /* same methods in other style */
marci@280
   264
    /* for experimental purpose */
marci@280
   265
marci@280
   266
    EachNodeIt& getFirst(EachNodeIt& v) const { 
marci@280
   267
      v=EachNodeIt(*this); return v; }
marci@280
   268
    EachEdgeIt& getFirst(EachEdgeIt& e) const { 
marci@280
   269
      e=EachEdgeIt(*this); return e; }
marci@280
   270
    OutEdgeIt& getFirst(OutEdgeIt& e, NodeIt v) const { 
marci@280
   271
      e=OutEdgeIt(v); return e; }
marci@280
   272
    InEdgeIt& getFirst(InEdgeIt& e, NodeIt v) const { 
marci@280
   273
      e=InEdgeIt(v); return e; }
marci@280
   274
    SymEdgeIt& getFirst(SymEdgeIt& e, NodeIt v) const { 
marci@280
   275
      e=SymEdgeIt(v); return e; }
marci@280
   276
    //void getTail(NodeIt& n, const EdgeIt& e) const { n=tail(e); }
marci@280
   277
    //void getHead(NodeIt& n, const EdgeIt& e) const { n=head(e); }
marci@280
   278
marci@280
   279
    //void getANode(NodeIt& n, const OutEdgeIt& e) const { n=e.aNode(); }
marci@280
   280
    //void getANode(NodeIt& n, const InEdgeIt& e) const { n=e.aNode(); }
marci@280
   281
    //void getANode(NodeIt& n, const SymEdgeIt& e) const { n=e.aNode(); }
marci@280
   282
    //void getBNode(NodeIt& n, const OutEdgeIt& e) const { n=e.bNode(); }
marci@280
   283
    //void getBNode(NodeIt& n, const InEdgeIt& e) const { n=e.bNode(); }
marci@280
   284
    //void getBNode(NodeIt& n, const SymEdgeIt& e) const { n=e.bNode(); }
marci@280
   285
    //void get_invalid(NodeIt& n) { n=NodeIt(); }
marci@280
   286
    //void get_invalid(EdgeIt& e) { e=EdgeIt(); }
marci@280
   287
    //void get_invalid(OutEdgeIt& e) { e=OutEdgeIt(); }
marci@280
   288
    //void get_invalid(InEdgeIt& e) { e=InEdgeIt(); }
marci@280
   289
    //void get_invalid(SymEdgeIt& e) { e=SymEdgeIt(); }
marci@280
   290
marci@280
   291
    template< typename It >
marci@280
   292
    It first() const { 
marci@280
   293
      It e;
marci@280
   294
      getFirst(e);
marci@280
   295
      return e; 
marci@280
   296
    }
marci@280
   297
marci@280
   298
    template< typename It >
marci@280
   299
    It first(NodeIt v) const { 
marci@280
   300
      It e;
marci@280
   301
      getFirst(e, v);
marci@280
   302
      return e; 
marci@280
   303
    }
marci@280
   304
marci@280
   305
    bool valid(NodeIt n) const { return n.valid(); }
marci@280
   306
    bool valid(EdgeIt e) const { return e.valid(); }
marci@280
   307
    
marci@280
   308
    template <typename It> It getNext(It it) const { 
marci@280
   309
      It tmp(it); return next(tmp); }
marci@280
   310
    template <typename It> It& next(It& it) const { return ++it; }
marci@280
   311
   
marci@280
   312
marci@280
   313
    /* for getting id's of graph objects */
marci@280
   314
    /* these are important for the implementation of property vectors */
marci@280
   315
marci@280
   316
    int id(NodeIt v) const { return v.node->id; }
marci@280
   317
    int id(EdgeIt e) const { return e.edge->id; }
marci@280
   318
marci@280
   319
    /* adding nodes and edges */
marci@280
   320
marci@280
   321
    NodeIt addNode() { return NodeIt(_add_node()); }
marci@280
   322
    EdgeIt addEdge(NodeIt u, NodeIt v) {
marci@280
   323
      return EdgeIt(_add_edge(u.node, v.node)); 
marci@280
   324
    }
marci@280
   325
marci@280
   326
    void erase(NodeIt i) { 
marci@280
   327
      while (first<OutEdgeIt>(i).valid()) erase(first<OutEdgeIt>(i));
marci@280
   328
      while (first<InEdgeIt>(i).valid()) erase(first<InEdgeIt>(i));
marci@280
   329
      _delete_node(i.node); 
marci@280
   330
    }
marci@280
   331
  
marci@280
   332
    void erase(EdgeIt e) { _delete_edge(e.edge); }
marci@280
   333
marci@280
   334
    void clear() { 
marci@280
   335
      while (first<EachNodeIt>().valid()) erase(first<EachNodeIt>());
marci@280
   336
    }
marci@280
   337
marci@280
   338
    void setTail(EdgeIt e, NodeIt tail) {
marci@280
   339
      _set_tail(e.edge, tail.node); 
marci@280
   340
    }
marci@280
   341
marci@280
   342
    void setHead(EdgeIt e, NodeIt head) {
marci@280
   343
      _set_head(e.edge, head.node); 
marci@280
   344
    }
marci@280
   345
marci@280
   346
    /* stream operations, for testing purpose */
marci@280
   347
marci@280
   348
    friend std::ostream& operator<<(std::ostream& os, const NodeIt& i) { 
marci@280
   349
      os << i.node->id; return os; 
marci@280
   350
    }
marci@280
   351
    friend std::ostream& operator<<(std::ostream& os, const EdgeIt& i) { 
marci@280
   352
      os << "(" << i.edge->_tail->id << "--" << i.edge->id << "->" << i.edge->_head->id << ")"; 
marci@280
   353
      return os; 
marci@280
   354
    }
marci@280
   355
marci@280
   356
    class NodeIt {
marci@280
   357
      friend class ListGraph;
marci@280
   358
      template <typename T> friend class NodeMap;
marci@280
   359
marci@280
   360
      friend class EdgeIt;
marci@280
   361
      friend class OutEdgeIt;
marci@280
   362
      friend class InEdgeIt;
marci@280
   363
      friend class SymEdgeIt;
marci@280
   364
      //public:  //FIXME: It is required by op= of EachNodeIt
marci@280
   365
    protected:
marci@280
   366
      node_item* node;
marci@280
   367
    protected:
marci@280
   368
      friend int ListGraph::id(NodeIt v) const; 
marci@280
   369
    public:
marci@280
   370
      NodeIt() : node(0) { }
marci@280
   371
      NodeIt(node_item* _node) : node(_node) { }
marci@280
   372
      bool valid() const { return (node!=0); }
marci@280
   373
      //void makeInvalid() { node=0; }
marci@280
   374
      friend bool operator==(const NodeIt& u, const NodeIt& v) { 
marci@280
   375
	return v.node==u.node; 
marci@280
   376
      } 
marci@280
   377
      friend bool operator!=(const NodeIt& u, const NodeIt& v) { 
marci@280
   378
	return v.node!=u.node; 
marci@280
   379
      } 
marci@280
   380
      friend std::ostream& operator<<(std::ostream& os, const NodeIt& i);
marci@280
   381
    };
marci@280
   382
    
marci@280
   383
    class EachNodeIt : public NodeIt {
marci@280
   384
      friend class ListGraph;
marci@280
   385
      //protected:
marci@280
   386
    public: //for everybody but marci
marci@280
   387
      EachNodeIt(const ListGraph& G) : NodeIt(G._first_node) { }
marci@280
   388
    public:
marci@280
   389
      EachNodeIt() : NodeIt() { }
marci@280
   390
      EachNodeIt(node_item* v) : NodeIt(v) { }
marci@280
   391
      EachNodeIt& operator++() { node=node->_next_node; return *this; }
marci@280
   392
      //FIXME::
marci@280
   393
      //      EachNodeIt& operator=(const NodeIt& e)
marci@280
   394
      //      { node=e.node; return *this; }
marci@280
   395
    };
marci@280
   396
marci@280
   397
    class EdgeIt {
marci@280
   398
      friend class ListGraph;
marci@280
   399
      template <typename T> friend class EdgeMap;
marci@280
   400
      
marci@280
   401
      friend class NodeIt;
marci@280
   402
      friend class EachNodeIt;
marci@280
   403
    protected:
marci@280
   404
      edge_item* edge;
marci@280
   405
      friend int ListGraph::id(EdgeIt e) const;
marci@280
   406
    public:
marci@280
   407
      EdgeIt() : edge(0) { }
marci@280
   408
      //EdgeIt() { }
marci@280
   409
      EdgeIt(edge_item* _edge) : edge(_edge) { }
marci@280
   410
      bool valid() const { return (edge!=0); }
marci@280
   411
      //void makeInvalid() { edge=0; }
marci@280
   412
      friend bool operator==(const EdgeIt& u, const EdgeIt& v) { 
marci@280
   413
	return v.edge==u.edge; 
marci@280
   414
      } 
marci@280
   415
      friend bool operator!=(const EdgeIt& u, const EdgeIt& v) { 
marci@280
   416
	return v.edge!=u.edge; 
marci@280
   417
      } 
marci@280
   418
    protected:
marci@280
   419
      NodeIt tailNode() const { return NodeIt(edge->_tail); }
marci@280
   420
      NodeIt headNode() const { return NodeIt(edge->_head); }
marci@280
   421
    public:
marci@280
   422
      friend std::ostream& operator<<(std::ostream& os, const EdgeIt& i);
marci@280
   423
    };
marci@280
   424
    
marci@280
   425
    class EachEdgeIt : public EdgeIt {
marci@280
   426
      friend class ListGraph;
marci@280
   427
      //protected: 
marci@280
   428
    public: //for alpar
marci@280
   429
      EachEdgeIt(const ListGraph& G) {
marci@280
   430
	node_item* v=G._first_node;
marci@280
   431
	if (v) edge=v->_first_out_edge; else edge=0;
marci@280
   432
	while (v && !edge) { v=v->_next_node; if (v) edge=v->_first_out_edge; }
marci@280
   433
      }
marci@280
   434
    public:
marci@280
   435
      EachEdgeIt() : EdgeIt() { }
marci@280
   436
      EachEdgeIt(edge_item* _e) : EdgeIt(_e) { }
marci@280
   437
      EachEdgeIt& operator++() { 
marci@280
   438
	node_item* v=edge->_tail;
marci@280
   439
	edge=edge->_next_out; 
marci@280
   440
	while (v && !edge) { v=v->_next_node; if (v) edge=v->_first_out_edge; }
marci@280
   441
	return *this;
marci@280
   442
      }
marci@280
   443
    };
marci@280
   444
    
marci@280
   445
    class OutEdgeIt : public EdgeIt {
marci@280
   446
      friend class ListGraph;
marci@280
   447
      //node_item* v;
marci@280
   448
      //protected: 
marci@280
   449
    public: //for alpar
marci@280
   450
      OutEdgeIt(const NodeIt& _v) /*: v(_v.node)*/ { edge=_v.node->_first_out_edge; }
marci@280
   451
    public:
marci@280
   452
      OutEdgeIt() : EdgeIt()/*, v(0)*/ { }
marci@280
   453
      OutEdgeIt(const ListGraph& G, NodeIt _v) /*: v(_v.node)*/ { edge=_v.node->_first_out_edge; }
marci@280
   454
      OutEdgeIt& operator++() { edge=edge->_next_out; return *this; }
marci@280
   455
    protected:
marci@280
   456
      NodeIt aNode() const { return NodeIt(edge->_tail); }
marci@280
   457
      NodeIt bNode() const { return NodeIt(edge->_head); }
marci@280
   458
    };
marci@280
   459
    
marci@280
   460
    class InEdgeIt : public EdgeIt {
marci@280
   461
      friend class ListGraph;
marci@280
   462
      //node_item* v;
marci@280
   463
      //protected:
marci@280
   464
    public: //for alpar
marci@280
   465
      InEdgeIt(const NodeIt& _v) /*: v(_v.node)*/ { edge=_v.node->_first_in_edge; }
marci@280
   466
    public:
marci@280
   467
      InEdgeIt() : EdgeIt()/*, v(0)*/ { }
marci@280
   468
      InEdgeIt(const ListGraph& G, NodeIt _v) /*: v(_v.node)*/ { edge=_v.node->_first_in_edge; }
marci@280
   469
      InEdgeIt& operator++() { edge=edge->_next_in; return *this; }
marci@280
   470
    protected:
marci@280
   471
      NodeIt aNode() const { return NodeIt(edge->_head); }
marci@280
   472
      NodeIt bNode() const { return NodeIt(edge->_tail); }
marci@280
   473
    };
marci@280
   474
marci@280
   475
    class SymEdgeIt : public EdgeIt {
marci@280
   476
      friend class ListGraph;
marci@280
   477
      bool out_or_in; //1 iff out, 0 iff in
marci@280
   478
      //node_item* v;
marci@280
   479
      //protected:
marci@280
   480
    public: //for alpar
marci@280
   481
      SymEdgeIt(const NodeIt& _v) /*: v(_v.node)*/ { 
marci@280
   482
	out_or_in=1;
marci@280
   483
	edge=_v.node->_first_out_edge; 
marci@280
   484
	if (!edge) { edge=_v.node->_first_in_edge; out_or_in=0; }
marci@280
   485
      }
marci@280
   486
    public:
marci@280
   487
      SymEdgeIt() : EdgeIt() /*, v(0)*/ { }
marci@280
   488
      SymEdgeIt(const ListGraph& G, NodeIt _v) /*: v(_v.node)*/ { 
marci@280
   489
	out_or_in=1;
marci@280
   490
	edge=_v.node->_first_out_edge; 
marci@280
   491
	if (!edge) { edge=_v.node->_first_in_edge; out_or_in=0; }
marci@280
   492
      }
marci@280
   493
      SymEdgeIt& operator++() { 
marci@280
   494
	if (out_or_in) { 
marci@280
   495
	  node_item* v=edge->_tail;
marci@280
   496
	  edge=edge->_next_out; 
marci@280
   497
	  if (!edge) { out_or_in=0; edge=v->_first_in_edge; }
marci@280
   498
	} else {
marci@280
   499
	  edge=edge->_next_in; 
marci@280
   500
	}
marci@280
   501
	return *this;
marci@280
   502
      }
marci@280
   503
    protected:
marci@280
   504
      NodeIt aNode() const { 
marci@280
   505
	return (out_or_in) ? NodeIt(edge->_tail) : NodeIt(edge->_head); }
marci@280
   506
      NodeIt bNode() const { 
marci@280
   507
	return (out_or_in) ? NodeIt(edge->_head) : NodeIt(edge->_tail); }
marci@280
   508
    };
marci@280
   509
marci@280
   510
  };
marci@280
   511
marci@280
   512
//   template< typename T >
marci@280
   513
//   T ListGraph::first() const { 
marci@280
   514
//     std::cerr << "Invalid use of template<typemane T> T ListGraph::first<T>();" << std::endl; 
marci@280
   515
//     return T(); 
marci@280
   516
//   }
marci@280
   517
marci@280
   518
//   template<>
marci@280
   519
//   ListGraph::EachNodeIt ListGraph::first<ListGraph::EachNodeIt>() const { 
marci@280
   520
//     return firstNode(); 
marci@280
   521
//   }
marci@280
   522
marci@280
   523
//   template<>
marci@280
   524
//   ListGraph::EachEdgeIt ListGraph::first<ListGraph::EachEdgeIt>() const { 
marci@280
   525
//     return firstEdge(); 
marci@280
   526
//   }
marci@280
   527
marci@280
   528
//   template< typename T >
marci@280
   529
//   T ListGraph::first(ListGraph::NodeIt v) const {
marci@280
   530
//     std::cerr << "Invalid use of template<typemane T> T ListGraph::first<T>(ListGRaph::NodeIt);" << std::endl; 
marci@280
   531
//     return T(); 
marci@280
   532
//   } 
marci@280
   533
marci@280
   534
//   template<>
marci@280
   535
//   ListGraph::OutEdgeIt ListGraph::first<ListGraph::OutEdgeIt>(const ListGraph::NodeIt v) const { 
marci@280
   536
//     return firstOutEdge(v); 
marci@280
   537
//   }
marci@280
   538
marci@280
   539
//   template<>
marci@280
   540
//   ListGraph::InEdgeIt ListGraph::first<ListGraph::InEdgeIt>(const ListGraph::NodeIt v) const { 
marci@280
   541
//     return firstInEdge(v); 
marci@280
   542
//   }
marci@280
   543
marci@280
   544
//   template<>
marci@280
   545
//   ListGraph::SymEdgeIt ListGraph::first<ListGraph::SymEdgeIt>(const ListGraph::NodeIt v) const { 
marci@280
   546
//     return firstSymEdge(v); 
marci@280
   547
//   }
marci@280
   548
marci@280
   549
marci@280
   550
} //namespace hugo
marci@280
   551
marci@280
   552
#endif //LIST_GRAPH_HH