src/lemon/list_graph.h
author alpar
Sun, 14 Nov 2004 11:16:36 +0000
changeset 990 407e4d47fdd3
parent 980 0f1044b7a3af
child 1010 072bddac076e
permissions -rw-r--r--
An 'unused variable' warning when compiled with gcc-3.2.2 is removed
     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  */
    16 
    17 #ifndef LEMON_LIST_GRAPH_H
    18 #define LEMON_LIST_GRAPH_H
    19 
    20 ///\ingroup graphs
    21 ///\file
    22 ///\brief ListGraph, SymListGraph, NodeSet and EdgeSet classes.
    23 
    24 #include <lemon/erasable_graph_extender.h>
    25 #include <lemon/clearable_graph_extender.h>
    26 #include <lemon/extendable_graph_extender.h>
    27 
    28 #include <lemon/iterable_graph_extender.h>
    29 
    30 #include <lemon/alteration_observer_registry.h>
    31 
    32 #include <lemon/default_map.h>
    33 
    34 
    35 namespace lemon {
    36 
    37   class ListGraphBase {
    38 
    39   protected:
    40     struct NodeT {
    41       int first_in,first_out;
    42       int prev, next;
    43     };
    44  
    45     struct EdgeT {
    46       int target, source;
    47       int prev_in, prev_out;
    48       int next_in, next_out;
    49     };
    50 
    51     std::vector<NodeT> nodes;
    52 
    53     int first_node;
    54 
    55     int first_free_node;
    56 
    57     std::vector<EdgeT> edges;
    58 
    59     int first_free_edge;
    60     
    61   public:
    62     
    63     typedef ListGraphBase Graph;
    64     
    65     class Node {
    66       friend class ListGraphBase;
    67     protected:
    68 
    69       int id;
    70       Node(int pid) { id = pid;}
    71 
    72     public:
    73       Node() {}
    74       Node (Invalid) { id = -1; }
    75       bool operator==(const Node& node) const {return id == node.id;}
    76       bool operator!=(const Node& node) const {return id != node.id;}
    77       bool operator<(const Node& node) const {return id < node.id;}
    78     };
    79 
    80     class Edge {
    81       friend class ListGraphBase;
    82     protected:
    83 
    84       int id;
    85       Edge(int pid) { id = pid;}
    86 
    87     public:
    88       Edge() {}
    89       Edge (Invalid) { id = -1; }
    90       bool operator==(const Edge& edge) const {return id == edge.id;}
    91       bool operator!=(const Edge& edge) const {return id != edge.id;}
    92       bool operator<(const Edge& edge) const {return id < edge.id;}
    93     };
    94 
    95 
    96 
    97     ListGraphBase()
    98       : nodes(), first_node(-1),
    99 	first_free_node(-1), edges(), first_free_edge(-1) {}
   100 
   101     
   102     /// Maximum node ID.
   103     
   104     /// Maximum node ID.
   105     ///\sa id(Node)
   106     int maxId(Node = INVALID) const { return nodes.size()-1; } 
   107 
   108     /// Maximum edge ID.
   109     
   110     /// Maximum edge ID.
   111     ///\sa id(Edge)
   112     int maxId(Edge = INVALID) const { return edges.size()-1; }
   113 
   114     Node source(Edge e) const { return edges[e.id].source; }
   115     Node target(Edge e) const { return edges[e.id].target; }
   116 
   117 
   118     void first(Node& node) const { 
   119       node.id = first_node;
   120     }
   121 
   122     void next(Node& node) const {
   123       node.id = nodes[node.id].next;
   124     }
   125 
   126 
   127     void first(Edge& e) const { 
   128       int n;
   129       for(n = first_node; 
   130 	  n!=-1 && nodes[n].first_in == -1; 
   131 	  n = nodes[n].next);
   132       e.id = (n == -1) ? -1 : nodes[n].first_in;
   133     }
   134 
   135     void next(Edge& edge) const {
   136       if (edges[edge.id].next_in != -1) {
   137 	edge.id = edges[edge.id].next_in;
   138       } else {
   139 	int n;
   140 	for(n = nodes[edges[edge.id].target].next;
   141 	  n!=-1 && nodes[n].first_in == -1; 
   142 	  n = nodes[n].next);
   143 	edge.id = (n == -1) ? -1 : nodes[n].first_in;
   144       }      
   145     }
   146 
   147     void firstOut(Edge &e, const Node& v) const {
   148       e.id = nodes[v.id].first_out;
   149     }
   150     void nextOut(Edge &e) const {
   151       e.id=edges[e.id].next_out;
   152     }
   153 
   154     void firstIn(Edge &e, const Node& v) const {
   155       e.id = nodes[v.id].first_in;
   156     }
   157     void nextIn(Edge &e) const {
   158       e.id=edges[e.id].next_in;
   159     }
   160 
   161     
   162     static int id(Node v) { return v.id; }
   163     static int id(Edge e) { return e.id; }
   164 
   165     /// Adds a new node to the graph.
   166 
   167     /// \warning It adds the new node to the front of the list.
   168     /// (i.e. the lastly added node becomes the first.)
   169     Node addNode() {     
   170       int n;
   171       
   172       if(first_free_node==-1) {
   173 	n = nodes.size();
   174 	nodes.push_back(NodeT());
   175       } else {
   176 	n = first_free_node;
   177 	first_free_node = nodes[n].next;
   178       }
   179       
   180       nodes[n].next = first_node;
   181       if(first_node != -1) nodes[first_node].prev = n;
   182       first_node = n;
   183       nodes[n].prev = -1;
   184       
   185       nodes[n].first_in = nodes[n].first_out = -1;
   186       
   187       return Node(n);
   188     }
   189     
   190     Edge addEdge(Node u, Node v) {
   191       int n;      
   192 
   193       if (first_free_edge == -1) {
   194 	n = edges.size();
   195 	edges.push_back(EdgeT());
   196       } else {
   197 	n = first_free_edge;
   198 	first_free_edge = edges[n].next_in;
   199       }
   200       
   201       edges[n].source = u.id; 
   202       edges[n].target = v.id;
   203 
   204       edges[n].next_out = nodes[u.id].first_out;
   205       if(nodes[u.id].first_out != -1) {
   206 	edges[nodes[u.id].first_out].prev_out = n;
   207       }
   208       
   209       edges[n].next_in = nodes[v.id].first_in;
   210       if(nodes[v.id].first_in != -1) {
   211 	edges[nodes[v.id].first_in].prev_in = n;
   212       }
   213       
   214       edges[n].prev_in = edges[n].prev_out = -1;
   215 	
   216       nodes[u.id].first_out = nodes[v.id].first_in = n;
   217 
   218       return Edge(n);
   219     }
   220     
   221     void erase(const Node& node) {
   222       int n = node.id;
   223       
   224       if(nodes[n].next != -1) {
   225 	nodes[nodes[n].next].prev = nodes[n].prev;
   226       }
   227       
   228       if(nodes[n].prev != -1) {
   229 	nodes[nodes[n].prev].next = nodes[n].next;
   230       } else {
   231 	first_node = nodes[n].next;
   232       }
   233       
   234       nodes[n].next = first_free_node;
   235       first_free_node = n;
   236 
   237     }
   238     
   239     void erase(const Edge& edge) {
   240       int n = edge.id;
   241       
   242       if(edges[n].next_in!=-1) {
   243 	edges[edges[n].next_in].prev_in = edges[n].prev_in;
   244       }
   245 
   246       if(edges[n].prev_in!=-1) {
   247 	edges[edges[n].prev_in].next_in = edges[n].next_in;
   248       } else {
   249 	nodes[edges[n].target].first_in = edges[n].next_in;
   250       }
   251 
   252       
   253       if(edges[n].next_out!=-1) {
   254 	edges[edges[n].next_out].prev_out = edges[n].prev_out;
   255       } 
   256 
   257       if(edges[n].prev_out!=-1) {
   258 	edges[edges[n].prev_out].next_out = edges[n].next_out;
   259       } else {
   260 	nodes[edges[n].source].first_out = edges[n].next_out;
   261       }
   262       
   263       edges[n].next_in = first_free_edge;
   264       first_free_edge = n;      
   265 
   266     }
   267 
   268     void clear() {
   269       edges.clear();
   270       nodes.clear();
   271       first_node = first_free_node = first_free_edge = -1;
   272     }
   273 
   274   protected:
   275     void _moveTarget(Edge e, Node n) 
   276     {
   277       if(edges[e.id].next_in != -1)
   278 	edges[edges[e.id].next_in].prev_in = edges[e.id].prev_in;
   279       if(edges[e.id].prev_in != -1)
   280 	edges[edges[e.id].prev_in].next_in = edges[e.id].next_in;
   281       else nodes[edges[e.id].target].first_in = edges[e.id].next_in;
   282       edges[e.id].target = n.id;
   283       edges[e.id].prev_in = -1;
   284       edges[e.id].next_in = nodes[n.id].first_in;
   285       nodes[n.id].first_in = e.id;
   286     }
   287     void _moveSource(Edge e, Node n) 
   288     {
   289       if(edges[e.id].next_out != -1)
   290 	edges[edges[e.id].next_out].prev_out = edges[e.id].prev_out;
   291       if(edges[e.id].prev_out != -1)
   292 	edges[edges[e.id].prev_out].next_out = edges[e.id].next_out;
   293       else nodes[edges[e.id].source].first_out = edges[e.id].next_out;
   294       edges[e.id].source = n.id;
   295       edges[e.id].prev_out = -1;
   296       edges[e.id].next_out = nodes[n.id].first_out;
   297       nodes[n.id].first_out = e.id;
   298     }
   299 
   300   };
   301 
   302   typedef AlterableGraphExtender<ListGraphBase> AlterableListGraphBase;
   303   typedef IterableGraphExtender<AlterableListGraphBase> IterableListGraphBase;
   304   typedef DefaultMappableGraphExtender<IterableListGraphBase> MappableListGraphBase;
   305   typedef ExtendableGraphExtender<MappableListGraphBase> ExtendableListGraphBase;
   306   typedef ClearableGraphExtender<ExtendableListGraphBase> ClearableListGraphBase;
   307   typedef ErasableGraphExtender<ClearableListGraphBase> ErasableListGraphBase;
   308 
   309 /// \addtogroup graphs
   310 /// @{
   311 
   312   ///A list graph class.
   313 
   314   ///This is a simple and fast erasable graph implementation.
   315   ///
   316   ///It conforms to the
   317   ///\ref concept::ErasableGraph "ErasableGraph" concept.
   318   ///\sa concept::ErasableGraph.
   319 
   320   class ListGraph : public ErasableListGraphBase 
   321   {
   322   public:
   323     /// Moves the target of \c e to \c n
   324 
   325     /// Moves the target of \c e to \c n
   326     ///
   327     void moveTarget(Edge e, Node n) { _moveTarget(e,n); }
   328     /// Moves the source of \c e to \c n
   329 
   330     /// Moves the source of \c e to \c n
   331     ///
   332     void moveSource(Edge e, Node n) { _moveSource(e,n); }
   333 
   334     ///Using this it possible to avoid the superfluous memory allocation.
   335     ///\todo more docs...
   336     void reserveEdge(int n) { edges.reserve(n); };
   337     
   338   };
   339   
   340   /// @}  
   341 } //namespace lemon
   342   
   343 
   344 #endif