src/lemon/list_graph.h
author alpar
Sat, 30 Oct 2004 16:30:12 +0000
changeset 948 bc86b64f958e
parent 946 c94ef40a22ce
child 949 b16a10926781
permissions -rw-r--r--
- moveHead() and moveTail() added. Not tested.
     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/idmappable_graph_extender.h>
    29 
    30 #include <lemon/iterable_graph_extender.h>
    31 
    32 #include <lemon/alteration_observer_registry.h>
    33 
    34 #include <lemon/default_map.h>
    35 
    36 
    37 namespace lemon {
    38 
    39   class ListGraphBase {
    40 
    41     struct NodeT {
    42       int first_in,first_out;
    43       int prev, next;
    44     };
    45  
    46     struct EdgeT {
    47       int head, tail;
    48       int prev_in, prev_out;
    49       int next_in, next_out;
    50     };
    51 
    52     std::vector<NodeT> nodes;
    53 
    54     int first_node;
    55 
    56     int first_free_node;
    57 
    58     std::vector<EdgeT> edges;
    59 
    60     int first_free_edge;
    61     
    62   public:
    63     
    64     typedef ListGraphBase Graph;
    65     
    66     class Node {
    67       friend class Graph;
    68     protected:
    69 
    70       int id;
    71       Node(int pid) { id = pid;}
    72 
    73     public:
    74       Node() {}
    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;}
    79     };
    80 
    81     class Edge {
    82       friend class Graph;
    83     protected:
    84 
    85       int id;
    86       Edge(int pid) { id = pid;}
    87 
    88     public:
    89       Edge() {}
    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;}
    94     };
    95 
    96 
    97 
    98     ListGraphBase()
    99       : nodes(), first_node(-1),
   100 	first_free_node(-1), edges(), first_free_edge(-1) {}
   101 
   102     
   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); };
   107     
   108     /// Maximum node ID.
   109     
   110     /// Maximum node ID.
   111     ///\sa id(Node)
   112     int maxNodeId() const { return nodes.size()-1; } 
   113 
   114     /// Maximum edge ID.
   115     
   116     /// Maximum edge ID.
   117     ///\sa id(Edge)
   118     int maxEdgeId() const { return edges.size()-1; }
   119 
   120     Node tail(Edge e) const { return edges[e.id].tail; }
   121     Node head(Edge e) const { return edges[e.id].head; }
   122 
   123 
   124     void first(Node& node) const { 
   125       node.id = first_node;
   126     }
   127 
   128     void next(Node& node) const {
   129       node.id = nodes[node.id].next;
   130     }
   131 
   132 
   133     void first(Edge& e) const { 
   134       int n;
   135       for(n = first_node; 
   136 	  n!=-1 && nodes[n].first_in == -1; 
   137 	  n = nodes[n].next);
   138       e.id = (n == -1) ? -1 : nodes[n].first_in;
   139     }
   140 
   141     void next(Edge& edge) const {
   142       if (edges[edge.id].next_in != -1) {
   143 	edge.id = edges[edge.id].next_in;
   144       } else {
   145 	int n;
   146 	for(n = nodes[edges[edge.id].head].next;
   147 	  n!=-1 && nodes[n].first_in == -1; 
   148 	  n = nodes[n].next);
   149 	edge.id = (n == -1) ? -1 : nodes[n].first_in;
   150       }      
   151     }
   152 
   153     void firstOut(Edge &e, const Node& v) const {
   154       e.id = nodes[v.id].first_out;
   155     }
   156     void nextOut(Edge &e) const {
   157       e.id=edges[e.id].next_out;
   158     }
   159 
   160     void firstIn(Edge &e, const Node& v) const {
   161       e.id = nodes[v.id].first_in;
   162     }
   163     void nextIn(Edge &e) const {
   164       e.id=edges[e.id].next_in;
   165     }
   166 
   167     
   168     static int id(Node v) { return v.id; }
   169     static int id(Edge e) { return e.id; }
   170 
   171     /// Adds a new node to the graph.
   172 
   173     /// \warning It adds the new node to the front of the list.
   174     /// (i.e. the lastly added node becomes the first.)
   175     Node addNode() {     
   176       int n;
   177       
   178       if(first_free_node==-1) {
   179 	n = nodes.size();
   180 	nodes.push_back(NodeT());
   181       } else {
   182 	n = first_free_node;
   183 	first_free_node = nodes[n].next;
   184       }
   185       
   186       nodes[n].next = first_node;
   187       if(first_node != -1) nodes[first_node].prev = n;
   188       first_node = n;
   189       nodes[n].prev = -1;
   190       
   191       nodes[n].first_in = nodes[n].first_out = -1;
   192       
   193       return Node(n);
   194     }
   195     
   196     Edge addEdge(Node u, Node v) {
   197       int n;      
   198 
   199       if (first_free_edge == -1) {
   200 	n = edges.size();
   201 	edges.push_back(EdgeT());
   202       } else {
   203 	n = first_free_edge;
   204 	first_free_edge = edges[n].next_in;
   205       }
   206       
   207       edges[n].tail = u.id; 
   208       edges[n].head = v.id;
   209 
   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;
   213       }
   214       
   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;
   218       }
   219       
   220       edges[n].prev_in = edges[n].prev_out = -1;
   221 	
   222       nodes[u.id].first_out = nodes[v.id].first_in = n;
   223 
   224       return Edge(n);
   225     }
   226     
   227     void erase(const Node& node) {
   228       int n = node.id;
   229       
   230       if(nodes[n].next != -1) {
   231 	nodes[nodes[n].next].prev = nodes[n].prev;
   232       }
   233       
   234       if(nodes[n].prev != -1) {
   235 	nodes[nodes[n].prev].next = nodes[n].next;
   236       } else {
   237 	first_node = nodes[n].next;
   238       }
   239       
   240       nodes[n].next = first_free_node;
   241       first_free_node = n;
   242 
   243     }
   244     
   245     void erase(const Edge& edge) {
   246       int n = edge.id;
   247       
   248       if(edges[n].next_in!=-1) {
   249 	edges[edges[n].next_in].prev_in = edges[n].prev_in;
   250       }
   251 
   252       if(edges[n].prev_in!=-1) {
   253 	edges[edges[n].prev_in].next_in = edges[n].next_in;
   254       } else {
   255 	nodes[edges[n].head].first_in = edges[n].next_in;
   256       }
   257 
   258       
   259       if(edges[n].next_out!=-1) {
   260 	edges[edges[n].next_out].prev_out = edges[n].prev_out;
   261       } 
   262 
   263       if(edges[n].prev_out!=-1) {
   264 	edges[edges[n].prev_out].next_out = edges[n].next_out;
   265       } else {
   266 	nodes[edges[n].tail].first_out = edges[n].next_out;
   267       }
   268       
   269       edges[n].next_in = first_free_edge;
   270       first_free_edge = n;      
   271 
   272     }
   273 
   274     void clear() {
   275       edges.clear();
   276       nodes.clear();
   277       first_node = first_free_node = first_free_edge = -1;
   278     }
   279 
   280   };
   281 
   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;
   289 
   290 /// \addtogroup graphs
   291 /// @{
   292 
   293   ///A list graph class.
   294 
   295   ///This is a simple and fast erasable graph implementation.
   296   ///
   297   ///It conforms to the
   298   ///\ref skeleton::ErasableGraph "ErasableGraph" concept.
   299   ///\sa skeleton::ErasableGraph.
   300 
   301   class ListGraph : public ErasableListGraphBase 
   302   {
   303   public:
   304     /// Moves the head of \c e to \c n
   305 
   306     /// Moves the head of \c e to \c n
   307     ///
   308     void moveHead(Edge e, Node n) 
   309     {
   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;
   319     }
   320     /// Moves the tail of \c e to \c n
   321 
   322     /// Moves the tail of \c e to \c n
   323     ///
   324     void moveTail(Edge e, Node n) 
   325     {
   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;
   335     }
   336   }
   337   /// @}  
   338 } //namespace lemon
   339   
   340 
   341 #endif