src/work/marci_list_graph.hh
author marci
Fri, 16 Jan 2004 11:20:09 +0000
changeset 15 e41c71268807
parent 9 a9ed3f1c2c63
child 16 dd19ef4d7ba4
permissions -rw-r--r--
new method for making invalid iterators: make_invalid()
marci@9
     1
#ifndef MARCI_LIST_GRAPH_HH
marci@9
     2
#define MARCI_LIST_GRAPH_HH
marci@9
     3
marci@9
     4
#include <iostream>
marci@9
     5
marci@9
     6
namespace marci {
marci@9
     7
marci@9
     8
  class list_graph {
marci@9
     9
    class node_item;
marci@9
    10
    class edge_item;
marci@9
    11
  public:
marci@9
    12
    class node_iterator;
marci@9
    13
    class each_node_iterator;
marci@9
    14
    class edge_iterator;
marci@9
    15
    class each_edge_iterator;
marci@9
    16
    class out_edge_iterator;
marci@9
    17
    class in_edge_iterator;
marci@9
    18
    class sym_edge_iterator;
marci@9
    19
  private:
marci@9
    20
    int node_id;
marci@9
    21
    int edge_id;
marci@9
    22
marci@9
    23
    node_item* _first_node;
marci@9
    24
    node_item* _last_node;
marci@9
    25
marci@9
    26
    class node_item {
marci@9
    27
      friend class list_graph;
marci@9
    28
      friend class node_iterator;
marci@9
    29
      friend class each_node_iterator;
marci@9
    30
      friend class edge_iterator;
marci@9
    31
      friend class each_edge_iterator;
marci@9
    32
      friend class out_edge_iterator;
marci@9
    33
      friend class in_edge_iterator;
marci@9
    34
      friend class sym_edge_iterator;
marci@9
    35
      friend std::ostream& operator<<(std::ostream& os, const node_iterator& i);
marci@9
    36
      friend std::ostream& operator<<(std::ostream& os, const edge_iterator& i);
marci@9
    37
      list_graph* G;
marci@9
    38
      int id;
marci@9
    39
      edge_item* _first_out_edge;
marci@9
    40
      edge_item* _last_out_edge;
marci@9
    41
      edge_item* _first_in_edge;
marci@9
    42
      edge_item* _last_in_edge;
marci@9
    43
      node_item* _next_node;
marci@9
    44
      node_item* _prev_node;
marci@9
    45
    public:
marci@9
    46
      node_item() { }
marci@9
    47
    };
marci@9
    48
marci@9
    49
    class edge_item {
marci@9
    50
      friend class list_graph;
marci@9
    51
      friend class node_iterator;
marci@9
    52
      friend class each_node_iterator;
marci@9
    53
      friend class edge_iterator;
marci@9
    54
      friend class each_edge_iterator;
marci@9
    55
      friend class out_edge_iterator;
marci@9
    56
      friend class in_edge_iterator;
marci@9
    57
      friend class sym_edge_iterator;
marci@9
    58
      friend std::ostream& operator<<(std::ostream& os, const edge_iterator& i);
marci@9
    59
      list_graph* G;
marci@9
    60
      int id;
marci@9
    61
      node_item* _tail;
marci@9
    62
      node_item* _head;
marci@9
    63
      edge_item* _next_out;
marci@9
    64
      edge_item* _prev_out;
marci@9
    65
      edge_item* _next_in;
marci@9
    66
      edge_item* _prev_in;
marci@9
    67
    public:
marci@9
    68
      edge_item() { }
marci@9
    69
    };
marci@9
    70
marci@9
    71
    node_item* _add_node() { 
marci@9
    72
      node_item* p=new node_item;
marci@9
    73
      p->id=node_id++;
marci@9
    74
      p->_first_out_edge=0;
marci@9
    75
      p->_last_out_edge=0;
marci@9
    76
      p->_first_in_edge=0;
marci@9
    77
      p->_last_in_edge=0;
marci@9
    78
      p->_prev_node=_last_node;
marci@9
    79
      p->_next_node=0;
marci@9
    80
      if (_last_node) _last_node->_next_node=p;
marci@9
    81
      _last_node=p;
marci@9
    82
      if (!_first_node) _first_node=p;
marci@9
    83
      return p;
marci@9
    84
    }
marci@9
    85
marci@9
    86
    edge_item* _add_edge(node_item* _tail, node_item* _head) {
marci@9
    87
      edge_item* e=new edge_item;
marci@9
    88
      e->id=edge_id++;
marci@9
    89
      e->_tail=_tail;
marci@9
    90
      e->_head=_head;
marci@9
    91
      
marci@9
    92
      e->_prev_out=_tail->_last_out_edge;
marci@9
    93
      if (_tail->_last_out_edge) (_tail->_last_out_edge)->_next_out=e;
marci@9
    94
      _tail->_last_out_edge=e;
marci@9
    95
      if (!_tail->_first_out_edge) _tail->_first_out_edge=e; 
marci@9
    96
       
marci@9
    97
      e->_prev_in=_head->_last_in_edge;
marci@9
    98
      if (_head->_last_in_edge) (_head->_last_in_edge)->_next_in=e;
marci@9
    99
      _head->_last_in_edge=e;
marci@9
   100
      if (!_head->_first_in_edge) { _head->_first_in_edge=e; } 
marci@9
   101
      return e;
marci@9
   102
    }
marci@9
   103
marci@9
   104
  public:
marci@9
   105
marci@9
   106
    /* default constructor */
marci@9
   107
marci@9
   108
    list_graph() : node_id(0), edge_id(0), _first_node(0), _last_node(0) { }
marci@9
   109
    
marci@9
   110
    /* functions to construct iterators from the graph, or from each other */
marci@9
   111
marci@9
   112
    each_node_iterator first_node() { return each_node_iterator(_first_node); }
marci@9
   113
    each_edge_iterator first_edge() { 
marci@9
   114
      node_item* v=_first_node;
marci@9
   115
      edge_item* edge=v->_first_out_edge;
marci@9
   116
      while (v && !edge) { v=v->_next_node; if (v) edge=v->_first_out_edge; }
marci@9
   117
      return each_edge_iterator(v, edge); 
marci@9
   118
    }
marci@9
   119
    
marci@9
   120
    out_edge_iterator first_out_edge(const node_iterator& v) { 
marci@9
   121
      return out_edge_iterator(v); 
marci@9
   122
    }
marci@9
   123
    in_edge_iterator first_in_edge(const node_iterator& v) { 
marci@9
   124
      return in_edge_iterator(v); 
marci@9
   125
    }
marci@9
   126
    sym_edge_iterator first_sym_edge(const node_iterator& v) { 
marci@9
   127
      return sym_edge_iterator(v); 
marci@9
   128
    }
marci@9
   129
    node_iterator tail(const edge_iterator& e) { return e.tail_node(); }
marci@9
   130
    node_iterator head(const edge_iterator& e) { return e.head_node(); }
marci@9
   131
marci@9
   132
    node_iterator a_node(const out_edge_iterator& e) { return e.a_node(); }
marci@9
   133
    node_iterator a_node(const in_edge_iterator& e) { return e.a_node(); }
marci@9
   134
    node_iterator a_node(const sym_edge_iterator& e) { return e.a_node(); }
marci@9
   135
marci@9
   136
    node_iterator b_node(const out_edge_iterator& e) { return e.b_node(); }
marci@9
   137
    node_iterator b_node(const in_edge_iterator& e) { return e.b_node(); }
marci@9
   138
    node_iterator b_node(const sym_edge_iterator& e) { return e.b_node(); }
marci@9
   139
marci@9
   140
    node_iterator invalid_node() { return node_iterator(); }
marci@9
   141
    edge_iterator invalid_edge() { return edge_iterator(); }
marci@9
   142
    out_edge_iterator invalid_out_edge() { return out_edge_iterator(); }
marci@9
   143
    in_edge_iterator invalid_in_edge() { return in_edge_iterator(); }
marci@9
   144
    sym_edge_iterator invalid_sym_edge() { return sym_edge_iterator(); }
marci@9
   145
marci@9
   146
    /* same methods in other style */
marci@9
   147
    /* for experimental purpose */
marci@9
   148
marci@9
   149
    void get_first(each_node_iterator& v) { v=each_node_iterator(_first_node); }
marci@9
   150
    void get_first(each_edge_iterator& e) { e=first_edge(); }
marci@9
   151
    void get_first(out_edge_iterator& e, const node_iterator& v) { 
marci@9
   152
      e=out_edge_iterator(v); 
marci@9
   153
    }
marci@9
   154
    void get_first(in_edge_iterator& e, const node_iterator& v) { 
marci@9
   155
      e=in_edge_iterator(v); 
marci@9
   156
    }
marci@9
   157
    void get_first(sym_edge_iterator& e, const node_iterator& v) { 
marci@9
   158
      e=sym_edge_iterator(v); 
marci@9
   159
    }
marci@9
   160
    void get_tail(node_iterator& n, const edge_iterator& e) { n=tail(e); }
marci@9
   161
    void get_head(node_iterator& n, const edge_iterator& e) { n=head(e); }
marci@9
   162
marci@9
   163
    void get_a_node(node_iterator& n, const out_edge_iterator& e) { n=e.a_node(); }
marci@9
   164
    void get_a_node(node_iterator& n, const in_edge_iterator& e) { n=e.a_node(); }
marci@9
   165
    void get_a_node(node_iterator& n, const sym_edge_iterator& e) { n=e.a_node(); }
marci@9
   166
    void get_b_node(node_iterator& n, const out_edge_iterator& e) { n=e.b_node(); }
marci@9
   167
    void get_b_node(node_iterator& n, const in_edge_iterator& e) { n=e.b_node(); }
marci@9
   168
    void get_b_node(node_iterator& n, const sym_edge_iterator& e) { n=e.b_node(); }
marci@9
   169
    void get_invalid(node_iterator& n) { n=node_iterator(); }
marci@9
   170
    void get_invalid(edge_iterator& e) { e=edge_iterator(); }
marci@9
   171
    void get_invalid(out_edge_iterator& e) { e=out_edge_iterator(); }
marci@9
   172
    void get_invalid(in_edge_iterator& e) { e=in_edge_iterator(); }
marci@9
   173
    void get_invalid(sym_edge_iterator& e) { e=sym_edge_iterator(); }
marci@9
   174
marci@9
   175
marci@9
   176
    /* for getting id's of graph objects */
marci@9
   177
    /* these are important for the implementation of property vectors */
marci@9
   178
marci@9
   179
    int id(const node_iterator& v) { return v.node->id; }
marci@9
   180
    int id(const edge_iterator& e) { return e.edge->id; }
marci@9
   181
marci@9
   182
    /* adding nodes and edges */
marci@9
   183
marci@9
   184
    node_iterator add_node() { return node_iterator(_add_node()); }
marci@9
   185
    edge_iterator add_edge(const node_iterator& u, const node_iterator& v) {
marci@9
   186
      return edge_iterator(_add_edge(u.node, v.node)); 
marci@9
   187
    }
marci@9
   188
marci@9
   189
    /* stream operations, for testing purpose */
marci@9
   190
marci@9
   191
    friend std::ostream& operator<<(std::ostream& os, const node_iterator& i) { 
marci@9
   192
      os << i.node->id; return os; 
marci@9
   193
    }
marci@9
   194
    friend std::ostream& operator<<(std::ostream& os, const edge_iterator& i) { 
marci@9
   195
      os << "(" << i.edge->_tail->id << "--" << i.edge->id << "->" << i.edge->_head->id << ")"; 
marci@9
   196
      return os; 
marci@9
   197
    }
marci@9
   198
marci@9
   199
    class node_iterator {
marci@9
   200
      friend class list_graph;
marci@9
   201
marci@9
   202
      friend class edge_iterator;
marci@9
   203
      friend class out_edge_iterator;
marci@9
   204
      friend class in_edge_iterator;
marci@9
   205
      friend class sym_edge_iterator;
marci@9
   206
    protected:
marci@9
   207
      node_item* node;
marci@9
   208
      friend int list_graph::id(const node_iterator& v); 
marci@9
   209
    public:
marci@9
   210
      node_iterator() : node(0) { }
marci@9
   211
      node_iterator(node_item* _node) : node(_node) { }
marci@9
   212
      bool is_valid() { return (node!=0); }
marci@9
   213
      friend bool operator==(const node_iterator& u, const node_iterator& v) { 
marci@9
   214
	return v.node==u.node; 
marci@9
   215
      } 
marci@9
   216
      friend bool operator!=(const node_iterator& u, const node_iterator& v) { 
marci@9
   217
	return v.node!=u.node; 
marci@9
   218
      } 
marci@9
   219
      friend std::ostream& operator<<(std::ostream& os, const node_iterator& i);
marci@9
   220
    };
marci@9
   221
    
marci@9
   222
    class each_node_iterator : public node_iterator {
marci@9
   223
      friend class list_graph;
marci@9
   224
    public:
marci@9
   225
      each_node_iterator() : node_iterator() { }
marci@9
   226
      each_node_iterator(node_item* v) : node_iterator(v) { }
marci@9
   227
      each_node_iterator& operator++() { node=node->_next_node; return *this; }
marci@9
   228
    };
marci@9
   229
marci@9
   230
    class edge_iterator {
marci@9
   231
      friend class list_graph;
marci@9
   232
      
marci@9
   233
      friend class node_iterator;
marci@9
   234
      friend class each_node_iterator;
marci@9
   235
    protected:
marci@9
   236
      edge_item* edge;
marci@9
   237
      friend int list_graph::id(const edge_iterator& e);
marci@9
   238
    public:
marci@9
   239
      edge_iterator() : edge(0) { }
marci@9
   240
      edge_iterator(edge_item* _edge) : edge(_edge) { }
marci@9
   241
      bool is_valid() { return (edge!=0); }
marci@9
   242
      friend bool operator==(const edge_iterator& u, const edge_iterator& v) { 
marci@9
   243
	return v.edge==u.edge; 
marci@9
   244
      } 
marci@9
   245
      friend bool operator!=(const edge_iterator& u, const edge_iterator& v) { 
marci@9
   246
	return v.edge!=u.edge; 
marci@9
   247
      } 
marci@9
   248
    protected:
marci@9
   249
      node_iterator tail_node() const { return node_iterator(edge->_tail); }
marci@9
   250
      node_iterator head_node() const { return node_iterator(edge->_head); }
marci@9
   251
    public:
marci@9
   252
      friend std::ostream& operator<<(std::ostream& os, const edge_iterator& i);
marci@9
   253
    };
marci@9
   254
    
marci@9
   255
    class each_edge_iterator : public edge_iterator {
marci@9
   256
      friend class list_graph;
marci@9
   257
      node_item* v;
marci@9
   258
    public:
marci@9
   259
      each_edge_iterator() : edge_iterator(), v(0) { }
marci@9
   260
      each_edge_iterator(node_item* _v, edge_item* _e) : edge_iterator(_e), v(_v) { }
marci@9
   261
      each_edge_iterator& operator++() { 
marci@9
   262
	edge=edge->_next_out; 
marci@9
   263
	while (v && !edge) { v=v->_next_node; if (v) edge=v->_first_out_edge; }
marci@9
   264
	return *this;
marci@9
   265
      }
marci@9
   266
    };
marci@9
   267
    
marci@9
   268
    class out_edge_iterator : public edge_iterator {
marci@9
   269
      friend class list_graph;
marci@9
   270
      node_item* v;
marci@9
   271
    public:
marci@9
   272
      out_edge_iterator() : edge_iterator(), v(0) { }
marci@9
   273
    protected:
marci@9
   274
      out_edge_iterator(const node_iterator& _v) : v(_v.node) { edge=v->_first_out_edge; }
marci@9
   275
    public:
marci@9
   276
      out_edge_iterator& operator++() { edge=edge->_next_out; return *this; }
marci@9
   277
    protected:
marci@9
   278
      node_iterator a_node() const { return node_iterator(v); }
marci@9
   279
      node_iterator b_node() const { 
marci@13
   280
	return (edge->_tail==v) ? node_iterator(edge->_head) : node_iterator(edge->_tail); }
marci@9
   281
    };
marci@9
   282
    
marci@9
   283
    class in_edge_iterator : public edge_iterator {
marci@9
   284
      friend class list_graph;
marci@9
   285
      node_item* v;
marci@9
   286
    public:
marci@9
   287
      in_edge_iterator() : edge_iterator(), v(0) { }
marci@9
   288
    protected:
marci@9
   289
      in_edge_iterator(const node_iterator& _v) : v(_v.node) { 
marci@9
   290
	edge=v->_first_in_edge; 
marci@9
   291
      }
marci@9
   292
    public:
marci@9
   293
      in_edge_iterator& operator++() { edge=edge->_next_in; return *this; }
marci@9
   294
    protected:
marci@9
   295
      node_iterator a_node() const { return node_iterator(v); }
marci@9
   296
      node_iterator b_node() const { 
marci@13
   297
	return (edge->_tail==v) ? node_iterator(edge->_head) : node_iterator(edge->_tail); }
marci@9
   298
    };
marci@9
   299
marci@9
   300
    class sym_edge_iterator : public edge_iterator {
marci@9
   301
      friend class list_graph;
marci@9
   302
      bool out_or_in; //1 iff out, 0 iff in
marci@9
   303
      node_item* v;
marci@9
   304
    public:
marci@9
   305
      sym_edge_iterator() : edge_iterator(), v(0) { }
marci@9
   306
    protected:
marci@9
   307
      sym_edge_iterator(const node_iterator& _v) : v(_v.node) { 
marci@9
   308
	out_or_in=1;
marci@9
   309
	edge=v->_first_out_edge; 
marci@9
   310
	if (!edge) { edge=v->_first_in_edge; out_or_in=0; }
marci@9
   311
      }
marci@9
   312
    public:
marci@9
   313
      sym_edge_iterator& operator++() { 
marci@9
   314
	if (out_or_in) { 
marci@9
   315
	  edge=edge->_next_out; 
marci@9
   316
	  if (!edge) { out_or_in=0; edge=v->_first_in_edge; }
marci@9
   317
	} else {
marci@9
   318
	  edge=edge->_next_in; 
marci@9
   319
	}
marci@9
   320
	return *this;
marci@9
   321
      }
marci@9
   322
    protected:
marci@9
   323
      node_iterator a_node() const { return node_iterator(v); }
marci@9
   324
      node_iterator b_node() const { 
marci@13
   325
	return (edge->_tail==v) ? node_iterator(edge->_head) : node_iterator(edge->_tail); }
marci@9
   326
    };
marci@9
   327
marci@9
   328
  };
marci@9
   329
marci@9
   330
marci@9
   331
marci@9
   332
} //namespace marci
marci@9
   333
marci@9
   334
#endif //MARCI_LIST_GRAPH_HH