1 #ifndef MARCI_LIST_GRAPH_HH
2 #define MARCI_LIST_GRAPH_HH
13 class each_node_iterator;
15 class each_edge_iterator;
16 class out_edge_iterator;
17 class in_edge_iterator;
18 class sym_edge_iterator;
23 node_item* _first_node;
24 node_item* _last_node;
27 friend class list_graph;
28 friend class node_iterator;
29 friend class each_node_iterator;
30 friend class edge_iterator;
31 friend class each_edge_iterator;
32 friend class out_edge_iterator;
33 friend class in_edge_iterator;
34 friend class sym_edge_iterator;
35 friend std::ostream& operator<<(std::ostream& os, const node_iterator& i);
36 friend std::ostream& operator<<(std::ostream& os, const edge_iterator& i);
39 edge_item* _first_out_edge;
40 edge_item* _last_out_edge;
41 edge_item* _first_in_edge;
42 edge_item* _last_in_edge;
43 node_item* _next_node;
44 node_item* _prev_node;
50 friend class list_graph;
51 friend class node_iterator;
52 friend class each_node_iterator;
53 friend class edge_iterator;
54 friend class each_edge_iterator;
55 friend class out_edge_iterator;
56 friend class in_edge_iterator;
57 friend class sym_edge_iterator;
58 friend std::ostream& operator<<(std::ostream& os, const edge_iterator& i);
71 node_item* _add_node() {
72 node_item* p=new node_item;
78 p->_prev_node=_last_node;
80 if (_last_node) _last_node->_next_node=p;
82 if (!_first_node) _first_node=p;
86 edge_item* _add_edge(node_item* _tail, node_item* _head) {
87 edge_item* e=new edge_item;
92 e->_prev_out=_tail->_last_out_edge;
93 if (_tail->_last_out_edge) (_tail->_last_out_edge)->_next_out=e;
94 _tail->_last_out_edge=e;
95 if (!_tail->_first_out_edge) _tail->_first_out_edge=e;
97 e->_prev_in=_head->_last_in_edge;
98 if (_head->_last_in_edge) (_head->_last_in_edge)->_next_in=e;
99 _head->_last_in_edge=e;
100 if (!_head->_first_in_edge) { _head->_first_in_edge=e; }
106 /* default constructor */
108 list_graph() : node_id(0), edge_id(0), _first_node(0), _last_node(0) { }
110 /* functions to construct iterators from the graph, or from each other */
112 each_node_iterator first_node() { return each_node_iterator(_first_node); }
113 each_edge_iterator first_edge() {
114 node_item* v=_first_node;
115 edge_item* edge=v->_first_out_edge;
116 while (v && !edge) { v=v->_next_node; if (v) edge=v->_first_out_edge; }
117 return each_edge_iterator(v, edge);
120 out_edge_iterator first_out_edge(const node_iterator& v) {
121 return out_edge_iterator(v);
123 in_edge_iterator first_in_edge(const node_iterator& v) {
124 return in_edge_iterator(v);
126 sym_edge_iterator first_sym_edge(const node_iterator& v) {
127 return sym_edge_iterator(v);
129 node_iterator tail(const edge_iterator& e) { return e.tail_node(); }
130 node_iterator head(const edge_iterator& e) { return e.head_node(); }
132 node_iterator a_node(const out_edge_iterator& e) { return e.a_node(); }
133 node_iterator a_node(const in_edge_iterator& e) { return e.a_node(); }
134 node_iterator a_node(const sym_edge_iterator& e) { return e.a_node(); }
136 node_iterator b_node(const out_edge_iterator& e) { return e.b_node(); }
137 node_iterator b_node(const in_edge_iterator& e) { return e.b_node(); }
138 node_iterator b_node(const sym_edge_iterator& e) { return e.b_node(); }
140 node_iterator invalid_node() { return node_iterator(); }
141 edge_iterator invalid_edge() { return edge_iterator(); }
142 out_edge_iterator invalid_out_edge() { return out_edge_iterator(); }
143 in_edge_iterator invalid_in_edge() { return in_edge_iterator(); }
144 sym_edge_iterator invalid_sym_edge() { return sym_edge_iterator(); }
146 /* same methods in other style */
147 /* for experimental purpose */
149 void get_first(each_node_iterator& v) { v=each_node_iterator(_first_node); }
150 void get_first(each_edge_iterator& e) { e=first_edge(); }
151 void get_first(out_edge_iterator& e, const node_iterator& v) {
152 e=out_edge_iterator(v);
154 void get_first(in_edge_iterator& e, const node_iterator& v) {
155 e=in_edge_iterator(v);
157 void get_first(sym_edge_iterator& e, const node_iterator& v) {
158 e=sym_edge_iterator(v);
160 void get_tail(node_iterator& n, const edge_iterator& e) { n=tail(e); }
161 void get_head(node_iterator& n, const edge_iterator& e) { n=head(e); }
163 void get_a_node(node_iterator& n, const out_edge_iterator& e) { n=e.a_node(); }
164 void get_a_node(node_iterator& n, const in_edge_iterator& e) { n=e.a_node(); }
165 void get_a_node(node_iterator& n, const sym_edge_iterator& e) { n=e.a_node(); }
166 void get_b_node(node_iterator& n, const out_edge_iterator& e) { n=e.b_node(); }
167 void get_b_node(node_iterator& n, const in_edge_iterator& e) { n=e.b_node(); }
168 void get_b_node(node_iterator& n, const sym_edge_iterator& e) { n=e.b_node(); }
169 void get_invalid(node_iterator& n) { n=node_iterator(); }
170 void get_invalid(edge_iterator& e) { e=edge_iterator(); }
171 void get_invalid(out_edge_iterator& e) { e=out_edge_iterator(); }
172 void get_invalid(in_edge_iterator& e) { e=in_edge_iterator(); }
173 void get_invalid(sym_edge_iterator& e) { e=sym_edge_iterator(); }
176 /* for getting id's of graph objects */
177 /* these are important for the implementation of property vectors */
179 int id(const node_iterator& v) { return v.node->id; }
180 int id(const edge_iterator& e) { return e.edge->id; }
182 /* adding nodes and edges */
184 node_iterator add_node() { return node_iterator(_add_node()); }
185 edge_iterator add_edge(const node_iterator& u, const node_iterator& v) {
186 return edge_iterator(_add_edge(u.node, v.node));
189 /* stream operations, for testing purpose */
191 friend std::ostream& operator<<(std::ostream& os, const node_iterator& i) {
192 os << i.node->id; return os;
194 friend std::ostream& operator<<(std::ostream& os, const edge_iterator& i) {
195 os << "(" << i.edge->_tail->id << "--" << i.edge->id << "->" << i.edge->_head->id << ")";
199 class node_iterator {
200 friend class list_graph;
202 friend class edge_iterator;
203 friend class out_edge_iterator;
204 friend class in_edge_iterator;
205 friend class sym_edge_iterator;
208 friend int list_graph::id(const node_iterator& v);
210 node_iterator() : node(0) { }
211 node_iterator(node_item* _node) : node(_node) { }
212 bool is_valid() { return (node!=0); }
213 friend bool operator==(const node_iterator& u, const node_iterator& v) {
214 return v.node==u.node;
216 friend bool operator!=(const node_iterator& u, const node_iterator& v) {
217 return v.node!=u.node;
219 friend std::ostream& operator<<(std::ostream& os, const node_iterator& i);
222 class each_node_iterator : public node_iterator {
223 friend class list_graph;
225 each_node_iterator() : node_iterator() { }
226 each_node_iterator(node_item* v) : node_iterator(v) { }
227 each_node_iterator& operator++() { node=node->_next_node; return *this; }
230 class edge_iterator {
231 friend class list_graph;
233 friend class node_iterator;
234 friend class each_node_iterator;
237 friend int list_graph::id(const edge_iterator& e);
239 edge_iterator() : edge(0) { }
240 edge_iterator(edge_item* _edge) : edge(_edge) { }
241 bool is_valid() { return (edge!=0); }
242 friend bool operator==(const edge_iterator& u, const edge_iterator& v) {
243 return v.edge==u.edge;
245 friend bool operator!=(const edge_iterator& u, const edge_iterator& v) {
246 return v.edge!=u.edge;
249 node_iterator tail_node() const { return node_iterator(edge->_tail); }
250 node_iterator head_node() const { return node_iterator(edge->_head); }
252 friend std::ostream& operator<<(std::ostream& os, const edge_iterator& i);
255 class each_edge_iterator : public edge_iterator {
256 friend class list_graph;
259 each_edge_iterator() : edge_iterator(), v(0) { }
260 each_edge_iterator(node_item* _v, edge_item* _e) : edge_iterator(_e), v(_v) { }
261 each_edge_iterator& operator++() {
262 edge=edge->_next_out;
263 while (v && !edge) { v=v->_next_node; if (v) edge=v->_first_out_edge; }
268 class out_edge_iterator : public edge_iterator {
269 friend class list_graph;
272 out_edge_iterator() : edge_iterator(), v(0) { }
274 out_edge_iterator(const node_iterator& _v) : v(_v.node) { edge=v->_first_out_edge; }
276 out_edge_iterator& operator++() { edge=edge->_next_out; return *this; }
278 node_iterator a_node() const { return node_iterator(v); }
279 node_iterator b_node() const {
280 return (edge->_tail==v) ? node_iterator(edge->_head) : node_iterator(v); }
283 class in_edge_iterator : public edge_iterator {
284 friend class list_graph;
287 in_edge_iterator() : edge_iterator(), v(0) { }
289 in_edge_iterator(const node_iterator& _v) : v(_v.node) {
290 edge=v->_first_in_edge;
293 in_edge_iterator& operator++() { edge=edge->_next_in; return *this; }
295 node_iterator a_node() const { return node_iterator(v); }
296 node_iterator b_node() const {
297 return (edge->_tail==v) ? node_iterator(edge->_head) : node_iterator(v); }
300 class sym_edge_iterator : public edge_iterator {
301 friend class list_graph;
302 bool out_or_in; //1 iff out, 0 iff in
305 sym_edge_iterator() : edge_iterator(), v(0) { }
307 sym_edge_iterator(const node_iterator& _v) : v(_v.node) {
309 edge=v->_first_out_edge;
310 if (!edge) { edge=v->_first_in_edge; out_or_in=0; }
313 sym_edge_iterator& operator++() {
315 edge=edge->_next_out;
316 if (!edge) { out_or_in=0; edge=v->_first_in_edge; }
323 node_iterator a_node() const { return node_iterator(v); }
324 node_iterator b_node() const {
325 return (edge->_tail==v) ? node_iterator(edge->_head) : node_iterator(v); }
334 #endif //MARCI_LIST_GRAPH_HH