COIN-OR::LEMON - Graph Library

source: lemon-0.x/src/lemon/list_graph.h @ 975:12b9993b217c

Last change on this file since 975:12b9993b217c was 975:12b9993b217c, checked in by marci, 19 years ago

for better compatibility with gcc-3.4

File size: 8.4 KB
RevLine 
[948]1/* -*- C++ -*-
2 * src/lemon/list_graph.h - Part of LEMON, a generic C++ optimization library
3 *
4 * Copyright (C) 2004 Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport
5 * (Egervary Combinatorial Optimization Research Group, EGRES).
6 *
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.
10 *
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
13 * purpose.
14 *
15 */
[395]16
[921]17#ifndef LEMON_LIST_GRAPH_H
18#define LEMON_LIST_GRAPH_H
[395]19
[948]20///\ingroup graphs
21///\file
22///\brief ListGraph, SymListGraph, NodeSet and EdgeSet classes.
23
[946]24#include <lemon/erasable_graph_extender.h>
25#include <lemon/clearable_graph_extender.h>
26#include <lemon/extendable_graph_extender.h>
[395]27
[946]28#include <lemon/idmappable_graph_extender.h>
[395]29
[946]30#include <lemon/iterable_graph_extender.h>
[395]31
[946]32#include <lemon/alteration_observer_registry.h>
[782]33
[946]34#include <lemon/default_map.h>
[782]35
36
[921]37namespace lemon {
[395]38
[946]39  class ListGraphBase {
[406]40
[949]41  protected:
[946]42    struct NodeT {
[397]43      int first_in,first_out;
44      int prev, next;
[395]45    };
[946]46 
47    struct EdgeT {
[397]48      int head, tail;
49      int prev_in, prev_out;
50      int next_in, next_out;
[395]51    };
52
53    std::vector<NodeT> nodes;
[946]54
[397]55    int first_node;
[946]56
[397]57    int first_free_node;
[946]58
[395]59    std::vector<EdgeT> edges;
[946]60
[397]61    int first_free_edge;
[395]62   
[782]63  public:
[395]64   
[946]65    typedef ListGraphBase Graph;
[397]66   
[946]67    class Node {
[975]68      friend class ListGraphBase;
[946]69    protected:
[395]70
[946]71      int id;
72      Node(int pid) { id = pid;}
[395]73
[946]74    public:
75      Node() {}
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;}
80    };
[782]81
[946]82    class Edge {
[975]83      friend class ListGraphBase;
[946]84    protected:
[782]85
[946]86      int id;
87      Edge(int pid) { id = pid;}
[395]88
[946]89    public:
90      Edge() {}
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;}
95    };
96
97
98
99    ListGraphBase()
[782]100      : nodes(), first_node(-1),
101        first_free_node(-1), edges(), first_free_edge(-1) {}
102
[395]103   
[813]104    /// Maximum node ID.
105   
106    /// Maximum node ID.
107    ///\sa id(Node)
108    int maxNodeId() const { return nodes.size()-1; }
[946]109
[813]110    /// Maximum edge ID.
111   
112    /// Maximum edge ID.
113    ///\sa id(Edge)
114    int maxEdgeId() const { return edges.size()-1; }
[395]115
[946]116    Node tail(Edge e) const { return edges[e.id].tail; }
117    Node head(Edge e) const { return edges[e.id].head; }
[395]118
119
[946]120    void first(Node& node) const {
121      node.id = first_node;
122    }
123
124    void next(Node& node) const {
125      node.id = nodes[node.id].next;
126    }
127
128
129    void first(Edge& e) const {
130      int n;
131      for(n = first_node;
132          n!=-1 && nodes[n].first_in == -1;
133          n = nodes[n].next);
134      e.id = (n == -1) ? -1 : nodes[n].first_in;
135    }
136
137    void next(Edge& edge) const {
138      if (edges[edge.id].next_in != -1) {
139        edge.id = edges[edge.id].next_in;
140      } else {
141        int n;
142        for(n = nodes[edges[edge.id].head].next;
143          n!=-1 && nodes[n].first_in == -1;
144          n = nodes[n].next);
145        edge.id = (n == -1) ? -1 : nodes[n].first_in;
146      }     
147    }
148
149    void firstOut(Edge &e, const Node& v) const {
150      e.id = nodes[v.id].first_out;
151    }
152    void nextOut(Edge &e) const {
153      e.id=edges[e.id].next_out;
154    }
155
156    void firstIn(Edge &e, const Node& v) const {
157      e.id = nodes[v.id].first_in;
158    }
159    void nextIn(Edge &e) const {
160      e.id=edges[e.id].next_in;
161    }
162
[813]163   
[946]164    static int id(Node v) { return v.id; }
165    static int id(Edge e) { return e.id; }
[395]166
[397]167    /// Adds a new node to the graph.
168
[813]169    /// \warning It adds the new node to the front of the list.
[397]170    /// (i.e. the lastly added node becomes the first.)
[946]171    Node addNode() {     
[397]172      int n;
173     
[946]174      if(first_free_node==-1) {
175        n = nodes.size();
176        nodes.push_back(NodeT());
177      } else {
[397]178        n = first_free_node;
179        first_free_node = nodes[n].next;
180      }
181     
182      nodes[n].next = first_node;
183      if(first_node != -1) nodes[first_node].prev = n;
184      first_node = n;
185      nodes[n].prev = -1;
186     
187      nodes[n].first_in = nodes[n].first_out = -1;
188     
[946]189      return Node(n);
[395]190    }
191   
192    Edge addEdge(Node u, Node v) {
[946]193      int n;     
194
195      if (first_free_edge == -1) {
196        n = edges.size();
197        edges.push_back(EdgeT());
198      } else {
[397]199        n = first_free_edge;
200        first_free_edge = edges[n].next_in;
201      }
202     
[946]203      edges[n].tail = u.id;
204      edges[n].head = v.id;
[395]205
[946]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;
209      }
210     
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;
214      }
215     
[397]216      edges[n].prev_in = edges[n].prev_out = -1;
217       
[946]218      nodes[u.id].first_out = nodes[v.id].first_in = n;
[397]219
[946]220      return Edge(n);
[395]221    }
[774]222   
[946]223    void erase(const Node& node) {
224      int n = node.id;
225     
226      if(nodes[n].next != -1) {
227        nodes[nodes[n].next].prev = nodes[n].prev;
228      }
229     
230      if(nodes[n].prev != -1) {
231        nodes[nodes[n].prev].next = nodes[n].next;
232      } else {
233        first_node = nodes[n].next;
234      }
235     
236      nodes[n].next = first_free_node;
237      first_free_node = n;
[395]238
[774]239    }
240   
[946]241    void erase(const Edge& edge) {
242      int n = edge.id;
[397]243     
[946]244      if(edges[n].next_in!=-1) {
[397]245        edges[edges[n].next_in].prev_in = edges[n].prev_in;
[946]246      }
247
248      if(edges[n].prev_in!=-1) {
[397]249        edges[edges[n].prev_in].next_in = edges[n].next_in;
[946]250      } else {
251        nodes[edges[n].head].first_in = edges[n].next_in;
252      }
253
[397]254     
[946]255      if(edges[n].next_out!=-1) {
[397]256        edges[edges[n].next_out].prev_out = edges[n].prev_out;
[946]257      }
258
259      if(edges[n].prev_out!=-1) {
[397]260        edges[edges[n].prev_out].next_out = edges[n].next_out;
[946]261      } else {
262        nodes[edges[n].tail].first_out = edges[n].next_out;
263      }
[397]264     
265      edges[n].next_in = first_free_edge;
[695]266      first_free_edge = n;     
[397]267
268    }
269
270    void clear() {
[782]271      edges.clear();
272      nodes.clear();
[946]273      first_node = first_free_node = first_free_edge = -1;
[937]274    }
275
[949]276  protected:
277    void _moveHead(Edge e, Node n)
278    {
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;
288    }
289    void _moveTail(Edge e, Node n)
290    {
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;
300    }
301
[919]302  };
[909]303
[946]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;
[400]311
[948]312/// \addtogroup graphs
313/// @{
[400]314
[948]315  ///A list graph class.
[400]316
[948]317  ///This is a simple and fast erasable graph implementation.
318  ///
319  ///It conforms to the
[959]320  ///\ref concept::ErasableGraph "ErasableGraph" concept.
321  ///\sa concept::ErasableGraph.
[782]322
[948]323  class ListGraph : public ErasableListGraphBase
324  {
325  public:
326    /// Moves the head of \c e to \c n
327
328    /// Moves the head of \c e to \c n
329    ///
[949]330    void moveHead(Edge e, Node n) { _moveHead(e,n); }
[948]331    /// Moves the tail of \c e to \c n
332
333    /// Moves the tail of \c e to \c n
334    ///
[949]335    void moveTail(Edge e, Node n) { _moveTail(e,n); }
336
337    ///Using this it possible to avoid the superfluous memory allocation.
338    ///\todo more docs...
339    void reserveEdge(int n) { edges.reserve(n); };
340   
341  };
342 
[948]343  /// @} 
344} //namespace lemon
[946]345 
[400]346
[946]347#endif
Note: See TracBrowser for help on using the repository browser.