COIN-OR::LEMON - Graph Library

source: lemon-0.x/src/lemon/list_graph.h @ 946:c94ef40a22ce

Last change on this file since 946:c94ef40a22ce was 946:c94ef40a22ce, checked in by Mihaly Barasz, 16 years ago

The graph_factory branch (@ 1321) has been merged to trunk.

File size: 6.2 KB
Line 
1// -*- c++ -*-
2
3#ifndef LEMON_LIST_GRAPH_H
4#define LEMON_LIST_GRAPH_H
5
6#include <lemon/erasable_graph_extender.h>
7#include <lemon/clearable_graph_extender.h>
8#include <lemon/extendable_graph_extender.h>
9
10#include <lemon/idmappable_graph_extender.h>
11
12#include <lemon/iterable_graph_extender.h>
13
14#include <lemon/alteration_observer_registry.h>
15
16#include <lemon/default_map.h>
17
18
19namespace lemon {
20
21  class ListGraphBase {
22
23    struct NodeT {
24      int first_in,first_out;
25      int prev, next;
26    };
27 
28    struct EdgeT {
29      int head, tail;
30      int prev_in, prev_out;
31      int next_in, next_out;
32    };
33
34    std::vector<NodeT> nodes;
35
36    int first_node;
37
38    int first_free_node;
39
40    std::vector<EdgeT> edges;
41
42    int first_free_edge;
43   
44  public:
45   
46    typedef ListGraphBase Graph;
47   
48    class Node {
49      friend class Graph;
50    protected:
51
52      int id;
53      Node(int pid) { id = pid;}
54
55    public:
56      Node() {}
57      Node (Invalid) { id = -1; }
58      bool operator==(const Node& node) const {return id == node.id;}
59      bool operator!=(const Node& node) const {return id != node.id;}
60      bool operator<(const Node& node) const {return id < node.id;}
61    };
62
63    class Edge {
64      friend class Graph;
65    protected:
66
67      int id;
68      Edge(int pid) { id = pid;}
69
70    public:
71      Edge() {}
72      Edge (Invalid) { id = -1; }
73      bool operator==(const Edge& edge) const {return id == edge.id;}
74      bool operator!=(const Edge& edge) const {return id != edge.id;}
75      bool operator<(const Edge& edge) const {return id < edge.id;}
76    };
77
78
79
80    ListGraphBase()
81      : nodes(), first_node(-1),
82        first_free_node(-1), edges(), first_free_edge(-1) {}
83
84   
85    ///it possible to avoid the superfluous memory allocation.
86    void reserveEdge(int n) { edges.reserve(n); };
87   
88    /// Maximum node ID.
89   
90    /// Maximum node ID.
91    ///\sa id(Node)
92    int maxNodeId() const { return nodes.size()-1; }
93
94    /// Maximum edge ID.
95   
96    /// Maximum edge ID.
97    ///\sa id(Edge)
98    int maxEdgeId() const { return edges.size()-1; }
99
100    Node tail(Edge e) const { return edges[e.id].tail; }
101    Node head(Edge e) const { return edges[e.id].head; }
102
103
104    void first(Node& node) const {
105      node.id = first_node;
106    }
107
108    void next(Node& node) const {
109      node.id = nodes[node.id].next;
110    }
111
112
113    void first(Edge& e) const {
114      int n;
115      for(n = first_node;
116          n!=-1 && nodes[n].first_in == -1;
117          n = nodes[n].next);
118      e.id = (n == -1) ? -1 : nodes[n].first_in;
119    }
120
121    void next(Edge& edge) const {
122      if (edges[edge.id].next_in != -1) {
123        edge.id = edges[edge.id].next_in;
124      } else {
125        int n;
126        for(n = nodes[edges[edge.id].head].next;
127          n!=-1 && nodes[n].first_in == -1;
128          n = nodes[n].next);
129        edge.id = (n == -1) ? -1 : nodes[n].first_in;
130      }     
131    }
132
133    void firstOut(Edge &e, const Node& v) const {
134      e.id = nodes[v.id].first_out;
135    }
136    void nextOut(Edge &e) const {
137      e.id=edges[e.id].next_out;
138    }
139
140    void firstIn(Edge &e, const Node& v) const {
141      e.id = nodes[v.id].first_in;
142    }
143    void nextIn(Edge &e) const {
144      e.id=edges[e.id].next_in;
145    }
146
147   
148    static int id(Node v) { return v.id; }
149    static int id(Edge e) { return e.id; }
150
151    /// Adds a new node to the graph.
152
153    /// \warning It adds the new node to the front of the list.
154    /// (i.e. the lastly added node becomes the first.)
155    Node addNode() {     
156      int n;
157     
158      if(first_free_node==-1) {
159        n = nodes.size();
160        nodes.push_back(NodeT());
161      } else {
162        n = first_free_node;
163        first_free_node = nodes[n].next;
164      }
165     
166      nodes[n].next = first_node;
167      if(first_node != -1) nodes[first_node].prev = n;
168      first_node = n;
169      nodes[n].prev = -1;
170     
171      nodes[n].first_in = nodes[n].first_out = -1;
172     
173      return Node(n);
174    }
175   
176    Edge addEdge(Node u, Node v) {
177      int n;     
178
179      if (first_free_edge == -1) {
180        n = edges.size();
181        edges.push_back(EdgeT());
182      } else {
183        n = first_free_edge;
184        first_free_edge = edges[n].next_in;
185      }
186     
187      edges[n].tail = u.id;
188      edges[n].head = v.id;
189
190      edges[n].next_out = nodes[u.id].first_out;
191      if(nodes[u.id].first_out != -1) {
192        edges[nodes[u.id].first_out].prev_out = n;
193      }
194     
195      edges[n].next_in = nodes[v.id].first_in;
196      if(nodes[v.id].first_in != -1) {
197        edges[nodes[v.id].first_in].prev_in = n;
198      }
199     
200      edges[n].prev_in = edges[n].prev_out = -1;
201       
202      nodes[u.id].first_out = nodes[v.id].first_in = n;
203
204      return Edge(n);
205    }
206   
207    void erase(const Node& node) {
208      int n = node.id;
209     
210      if(nodes[n].next != -1) {
211        nodes[nodes[n].next].prev = nodes[n].prev;
212      }
213     
214      if(nodes[n].prev != -1) {
215        nodes[nodes[n].prev].next = nodes[n].next;
216      } else {
217        first_node = nodes[n].next;
218      }
219     
220      nodes[n].next = first_free_node;
221      first_free_node = n;
222
223    }
224   
225    void erase(const Edge& edge) {
226      int n = edge.id;
227     
228      if(edges[n].next_in!=-1) {
229        edges[edges[n].next_in].prev_in = edges[n].prev_in;
230      }
231
232      if(edges[n].prev_in!=-1) {
233        edges[edges[n].prev_in].next_in = edges[n].next_in;
234      } else {
235        nodes[edges[n].head].first_in = edges[n].next_in;
236      }
237
238     
239      if(edges[n].next_out!=-1) {
240        edges[edges[n].next_out].prev_out = edges[n].prev_out;
241      }
242
243      if(edges[n].prev_out!=-1) {
244        edges[edges[n].prev_out].next_out = edges[n].next_out;
245      } else {
246        nodes[edges[n].tail].first_out = edges[n].next_out;
247      }
248     
249      edges[n].next_in = first_free_edge;
250      first_free_edge = n;     
251
252    }
253
254    void clear() {
255      edges.clear();
256      nodes.clear();
257      first_node = first_free_node = first_free_edge = -1;
258    }
259
260  };
261
262  typedef AlterableGraphExtender<ListGraphBase> AlterableListGraphBase;
263  typedef IterableGraphExtender<AlterableListGraphBase> IterableListGraphBase;
264  typedef IdMappableGraphExtender<IterableListGraphBase> IdMappableListGraphBase;
265  typedef DefaultMappableGraphExtender<IdMappableListGraphBase> MappableListGraphBase;
266  typedef ExtendableGraphExtender<MappableListGraphBase> ExtendableListGraphBase;
267  typedef ClearableGraphExtender<ExtendableListGraphBase> ClearableListGraphBase;
268  typedef ErasableGraphExtender<ClearableListGraphBase> ErasableListGraphBase;
269
270  typedef ErasableListGraphBase ListGraph;
271
272}
273
274
275 
276
277#endif
Note: See TracBrowser for help on using the repository browser.