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