- moveHead() and moveTail() added. Not tested.
2 * src/lemon/list_graph.h - Part of LEMON, a generic C++ optimization library
4 * Copyright (C) 2004 Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport
5 * (Egervary Combinatorial Optimization Research Group, EGRES).
7 * Permission to use, modify and distribute this software is granted
8 * provided that this copyright notice appears in all copies. For
9 * precise terms see the accompanying LICENSE file.
11 * This software is provided "AS IS" with no warranty of any kind,
12 * express or implied, and with no claim as to its suitability for any
17 #ifndef LEMON_LIST_GRAPH_H
18 #define LEMON_LIST_GRAPH_H
22 ///\brief ListGraph, SymListGraph, NodeSet and EdgeSet classes.
24 #include <lemon/erasable_graph_extender.h>
25 #include <lemon/clearable_graph_extender.h>
26 #include <lemon/extendable_graph_extender.h>
28 #include <lemon/idmappable_graph_extender.h>
30 #include <lemon/iterable_graph_extender.h>
32 #include <lemon/alteration_observer_registry.h>
34 #include <lemon/default_map.h>
42 int first_in,first_out;
48 int prev_in, prev_out;
49 int next_in, next_out;
52 std::vector<NodeT> nodes;
58 std::vector<EdgeT> edges;
64 typedef ListGraphBase Graph;
71 Node(int pid) { id = pid;}
75 Node (Invalid) { id = -1; }
76 bool operator==(const Node& node) const {return id == node.id;}
77 bool operator!=(const Node& node) const {return id != node.id;}
78 bool operator<(const Node& node) const {return id < node.id;}
86 Edge(int pid) { id = pid;}
90 Edge (Invalid) { id = -1; }
91 bool operator==(const Edge& edge) const {return id == edge.id;}
92 bool operator!=(const Edge& edge) const {return id != edge.id;}
93 bool operator<(const Edge& edge) const {return id < edge.id;}
99 : nodes(), first_node(-1),
100 first_free_node(-1), edges(), first_free_edge(-1) {}
103 ///Using this it possible to avoid the superfluous memory allocation.
104 ///\todo more docs...
105 ///\todo It should be defined in ListGraph.
106 void reserveEdge(int n) { edges.reserve(n); };
112 int maxNodeId() const { return nodes.size()-1; }
118 int maxEdgeId() const { return edges.size()-1; }
120 Node tail(Edge e) const { return edges[e.id].tail; }
121 Node head(Edge e) const { return edges[e.id].head; }
124 void first(Node& node) const {
125 node.id = first_node;
128 void next(Node& node) const {
129 node.id = nodes[node.id].next;
133 void first(Edge& e) const {
136 n!=-1 && nodes[n].first_in == -1;
138 e.id = (n == -1) ? -1 : nodes[n].first_in;
141 void next(Edge& edge) const {
142 if (edges[edge.id].next_in != -1) {
143 edge.id = edges[edge.id].next_in;
146 for(n = nodes[edges[edge.id].head].next;
147 n!=-1 && nodes[n].first_in == -1;
149 edge.id = (n == -1) ? -1 : nodes[n].first_in;
153 void firstOut(Edge &e, const Node& v) const {
154 e.id = nodes[v.id].first_out;
156 void nextOut(Edge &e) const {
157 e.id=edges[e.id].next_out;
160 void firstIn(Edge &e, const Node& v) const {
161 e.id = nodes[v.id].first_in;
163 void nextIn(Edge &e) const {
164 e.id=edges[e.id].next_in;
168 static int id(Node v) { return v.id; }
169 static int id(Edge e) { return e.id; }
171 /// Adds a new node to the graph.
173 /// \warning It adds the new node to the front of the list.
174 /// (i.e. the lastly added node becomes the first.)
178 if(first_free_node==-1) {
180 nodes.push_back(NodeT());
183 first_free_node = nodes[n].next;
186 nodes[n].next = first_node;
187 if(first_node != -1) nodes[first_node].prev = n;
191 nodes[n].first_in = nodes[n].first_out = -1;
196 Edge addEdge(Node u, Node v) {
199 if (first_free_edge == -1) {
201 edges.push_back(EdgeT());
204 first_free_edge = edges[n].next_in;
207 edges[n].tail = u.id;
208 edges[n].head = v.id;
210 edges[n].next_out = nodes[u.id].first_out;
211 if(nodes[u.id].first_out != -1) {
212 edges[nodes[u.id].first_out].prev_out = n;
215 edges[n].next_in = nodes[v.id].first_in;
216 if(nodes[v.id].first_in != -1) {
217 edges[nodes[v.id].first_in].prev_in = n;
220 edges[n].prev_in = edges[n].prev_out = -1;
222 nodes[u.id].first_out = nodes[v.id].first_in = n;
227 void erase(const Node& node) {
230 if(nodes[n].next != -1) {
231 nodes[nodes[n].next].prev = nodes[n].prev;
234 if(nodes[n].prev != -1) {
235 nodes[nodes[n].prev].next = nodes[n].next;
237 first_node = nodes[n].next;
240 nodes[n].next = first_free_node;
245 void erase(const Edge& edge) {
248 if(edges[n].next_in!=-1) {
249 edges[edges[n].next_in].prev_in = edges[n].prev_in;
252 if(edges[n].prev_in!=-1) {
253 edges[edges[n].prev_in].next_in = edges[n].next_in;
255 nodes[edges[n].head].first_in = edges[n].next_in;
259 if(edges[n].next_out!=-1) {
260 edges[edges[n].next_out].prev_out = edges[n].prev_out;
263 if(edges[n].prev_out!=-1) {
264 edges[edges[n].prev_out].next_out = edges[n].next_out;
266 nodes[edges[n].tail].first_out = edges[n].next_out;
269 edges[n].next_in = first_free_edge;
277 first_node = first_free_node = first_free_edge = -1;
282 typedef AlterableGraphExtender<ListGraphBase> AlterableListGraphBase;
283 typedef IterableGraphExtender<AlterableListGraphBase> IterableListGraphBase;
284 typedef IdMappableGraphExtender<IterableListGraphBase> IdMappableListGraphBase;
285 typedef DefaultMappableGraphExtender<IdMappableListGraphBase> MappableListGraphBase;
286 typedef ExtendableGraphExtender<MappableListGraphBase> ExtendableListGraphBase;
287 typedef ClearableGraphExtender<ExtendableListGraphBase> ClearableListGraphBase;
288 typedef ErasableGraphExtender<ClearableListGraphBase> ErasableListGraphBase;
290 /// \addtogroup graphs
293 ///A list graph class.
295 ///This is a simple and fast erasable graph implementation.
297 ///It conforms to the
298 ///\ref skeleton::ErasableGraph "ErasableGraph" concept.
299 ///\sa skeleton::ErasableGraph.
301 class ListGraph : public ErasableListGraphBase
304 /// Moves the head of \c e to \c n
306 /// Moves the head of \c e to \c n
308 void moveHead(Edge e, Node n)
310 if(edges[e.n].next_in != -1)
311 edges[edges[e.n].next_in].prev_in = edges[e.n].prev_in;
312 if(edges[e.n].prev_in != -1)
313 edges[edges[e.n].prev_in].next_in = edges[e.n].next_in;
314 else nodes[edges[e.n].head].first_in = edges[e.n].next_in;
315 edges[e.n].head = n.n;
316 edges[e.n].prev_in = -1;
317 edges[e.n].next_in = nodes[n.n].first_in;
318 nodes[n.n].first_in = e.n;
320 /// Moves the tail of \c e to \c n
322 /// Moves the tail of \c e to \c n
324 void moveTail(Edge e, Node n)
326 if(edges[e.n].next_out != -1)
327 edges[edges[e.n].next_out].prev_out = edges[e.n].prev_out;
328 if(edges[e.n].prev_out != -1)
329 edges[edges[e.n].prev_out].next_out = edges[e.n].next_out;
330 else nodes[edges[e.n].tail].first_out = edges[e.n].next_out;
331 edges[e.n].tail = n.n;
332 edges[e.n].prev_out = -1;
333 edges[e.n].next_out = nodes[n.n].first_out;
334 nodes[n.n].first_out = e.n;