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