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