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>
43 int first_in,first_out;
49 int prev_in, prev_out;
50 int next_in, next_out;
53 std::vector<NodeT> nodes;
59 std::vector<EdgeT> edges;
65 typedef ListGraphBase Graph;
72 Node(int pid) { id = pid;}
76 Node (Invalid) { id = -1; }
77 bool operator==(const Node& node) const {return id == node.id;}
78 bool operator!=(const Node& node) const {return id != node.id;}
79 bool operator<(const Node& node) const {return id < node.id;}
87 Edge(int pid) { id = pid;}
91 Edge (Invalid) { id = -1; }
92 bool operator==(const Edge& edge) const {return id == edge.id;}
93 bool operator!=(const Edge& edge) const {return id != edge.id;}
94 bool operator<(const Edge& edge) const {return id < edge.id;}
100 : nodes(), first_node(-1),
101 first_free_node(-1), edges(), first_free_edge(-1) {}
108 int maxNodeId() const { return nodes.size()-1; }
114 int maxEdgeId() const { return edges.size()-1; }
116 Node tail(Edge e) const { return edges[e.id].tail; }
117 Node head(Edge e) const { return edges[e.id].head; }
120 void first(Node& node) const {
121 node.id = first_node;
124 void next(Node& node) const {
125 node.id = nodes[node.id].next;
129 void first(Edge& e) const {
132 n!=-1 && nodes[n].first_in == -1;
134 e.id = (n == -1) ? -1 : nodes[n].first_in;
137 void next(Edge& edge) const {
138 if (edges[edge.id].next_in != -1) {
139 edge.id = edges[edge.id].next_in;
142 for(n = nodes[edges[edge.id].head].next;
143 n!=-1 && nodes[n].first_in == -1;
145 edge.id = (n == -1) ? -1 : nodes[n].first_in;
149 void firstOut(Edge &e, const Node& v) const {
150 e.id = nodes[v.id].first_out;
152 void nextOut(Edge &e) const {
153 e.id=edges[e.id].next_out;
156 void firstIn(Edge &e, const Node& v) const {
157 e.id = nodes[v.id].first_in;
159 void nextIn(Edge &e) const {
160 e.id=edges[e.id].next_in;
164 static int id(Node v) { return v.id; }
165 static int id(Edge e) { return e.id; }
167 /// Adds a new node to the graph.
169 /// \warning It adds the new node to the front of the list.
170 /// (i.e. the lastly added node becomes the first.)
174 if(first_free_node==-1) {
176 nodes.push_back(NodeT());
179 first_free_node = nodes[n].next;
182 nodes[n].next = first_node;
183 if(first_node != -1) nodes[first_node].prev = n;
187 nodes[n].first_in = nodes[n].first_out = -1;
192 Edge addEdge(Node u, Node v) {
195 if (first_free_edge == -1) {
197 edges.push_back(EdgeT());
200 first_free_edge = edges[n].next_in;
203 edges[n].tail = u.id;
204 edges[n].head = v.id;
206 edges[n].next_out = nodes[u.id].first_out;
207 if(nodes[u.id].first_out != -1) {
208 edges[nodes[u.id].first_out].prev_out = n;
211 edges[n].next_in = nodes[v.id].first_in;
212 if(nodes[v.id].first_in != -1) {
213 edges[nodes[v.id].first_in].prev_in = n;
216 edges[n].prev_in = edges[n].prev_out = -1;
218 nodes[u.id].first_out = nodes[v.id].first_in = n;
223 void erase(const Node& node) {
226 if(nodes[n].next != -1) {
227 nodes[nodes[n].next].prev = nodes[n].prev;
230 if(nodes[n].prev != -1) {
231 nodes[nodes[n].prev].next = nodes[n].next;
233 first_node = nodes[n].next;
236 nodes[n].next = first_free_node;
241 void erase(const Edge& edge) {
244 if(edges[n].next_in!=-1) {
245 edges[edges[n].next_in].prev_in = edges[n].prev_in;
248 if(edges[n].prev_in!=-1) {
249 edges[edges[n].prev_in].next_in = edges[n].next_in;
251 nodes[edges[n].head].first_in = edges[n].next_in;
255 if(edges[n].next_out!=-1) {
256 edges[edges[n].next_out].prev_out = edges[n].prev_out;
259 if(edges[n].prev_out!=-1) {
260 edges[edges[n].prev_out].next_out = edges[n].next_out;
262 nodes[edges[n].tail].first_out = edges[n].next_out;
265 edges[n].next_in = first_free_edge;
273 first_node = first_free_node = first_free_edge = -1;
277 void _moveHead(Edge e, Node n)
279 if(edges[e.id].next_in != -1)
280 edges[edges[e.id].next_in].prev_in = edges[e.id].prev_in;
281 if(edges[e.id].prev_in != -1)
282 edges[edges[e.id].prev_in].next_in = edges[e.id].next_in;
283 else nodes[edges[e.id].head].first_in = edges[e.id].next_in;
284 edges[e.id].head = n.id;
285 edges[e.id].prev_in = -1;
286 edges[e.id].next_in = nodes[n.id].first_in;
287 nodes[n.id].first_in = e.id;
289 void _moveTail(Edge e, Node n)
291 if(edges[e.id].next_out != -1)
292 edges[edges[e.id].next_out].prev_out = edges[e.id].prev_out;
293 if(edges[e.id].prev_out != -1)
294 edges[edges[e.id].prev_out].next_out = edges[e.id].next_out;
295 else nodes[edges[e.id].tail].first_out = edges[e.id].next_out;
296 edges[e.id].tail = n.id;
297 edges[e.id].prev_out = -1;
298 edges[e.id].next_out = nodes[n.id].first_out;
299 nodes[n.id].first_out = e.id;
304 typedef AlterableGraphExtender<ListGraphBase> AlterableListGraphBase;
305 typedef IterableGraphExtender<AlterableListGraphBase> IterableListGraphBase;
306 typedef IdMappableGraphExtender<IterableListGraphBase> IdMappableListGraphBase;
307 typedef DefaultMappableGraphExtender<IdMappableListGraphBase> MappableListGraphBase;
308 typedef ExtendableGraphExtender<MappableListGraphBase> ExtendableListGraphBase;
309 typedef ClearableGraphExtender<ExtendableListGraphBase> ClearableListGraphBase;
310 typedef ErasableGraphExtender<ClearableListGraphBase> ErasableListGraphBase;
312 /// \addtogroup graphs
315 ///A list graph class.
317 ///This is a simple and fast erasable graph implementation.
319 ///It conforms to the
320 ///\ref concept::ErasableGraph "ErasableGraph" concept.
321 ///\sa concept::ErasableGraph.
323 class ListGraph : public ErasableListGraphBase
326 /// Moves the head of \c e to \c n
328 /// Moves the head of \c e to \c n
330 void moveHead(Edge e, Node n) { _moveHead(e,n); }
331 /// Moves the tail of \c e to \c n
333 /// Moves the tail of \c e to \c n
335 void moveTail(Edge e, Node n) { _moveTail(e,n); }
337 ///Using this it possible to avoid the superfluous memory allocation.
338 ///\todo more docs...
339 void reserveEdge(int n) { edges.reserve(n); };