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