src/work/deba/list_graph.h
author deba
Wed, 08 Sep 2004 12:06:45 +0000
changeset 822 88226d9fe821
parent 702 4207f82a1778
child 880 9d0bfd35b97c
permissions -rw-r--r--
The MapFactories have been removed from the code because
if we use macros then they increases only the complexity.

The pair iterators of the maps are separeted from the maps.

Some macros and comments has been changed.
     1 // -*- mode:C++ -*-
     2 
     3 #ifndef HUGO_LIST_GRAPH_H
     4 #define HUGO_LIST_GRAPH_H
     5 
     6 ///\ingroup graphs
     7 ///\file
     8 ///\brief ListGraph, SymListGraph, NodeSet and EdgeSet classes.
     9 
    10 #include <vector>
    11 #include <climits>
    12 
    13 #include "invalid.h"
    14 
    15 #include "array_map_factory.h"
    16 #include "map_registry.h"
    17 
    18 #include "map_defines.h"
    19 
    20 namespace hugo {
    21 
    22 /// \addtogroup graphs
    23 /// @{
    24 
    25   ///A list graph class.
    26 
    27   ///This is a simple and fast erasable graph implementation.
    28   ///
    29   ///It conforms to the graph interface documented under
    30   ///the description of \ref GraphSkeleton.
    31   ///\sa \ref GraphSkeleton.
    32   class ListGraph {
    33 
    34     //Nodes are double linked.
    35     //The free nodes are only single linked using the "next" field.
    36     struct NodeT 
    37     {
    38       int first_in,first_out;
    39       int prev, next;
    40       //      NodeT() {}
    41     };
    42     //Edges are double linked.
    43     //The free edges are only single linked using the "next_in" field.
    44     struct EdgeT 
    45     {
    46       int head, tail;
    47       int prev_in, prev_out;
    48       int next_in, next_out;
    49       //FIXME: is this necessary?
    50       //      EdgeT() : next_in(-1), next_out(-1) prev_in(-1), prev_out(-1) {}  
    51     };
    52 
    53     std::vector<NodeT> nodes;
    54     //The first node
    55     int first_node;
    56     //The first free node
    57     int first_free_node;
    58     std::vector<EdgeT> edges;
    59     //The first free edge
    60     int first_free_edge;
    61     
    62   protected:
    63     
    64   public:
    65     
    66     class Node;
    67     class Edge;
    68 
    69     typedef ListGraph Graph;
    70 
    71   public:
    72 
    73     class NodeIt;
    74     class EdgeIt;
    75     class OutEdgeIt;
    76     class InEdgeIt;
    77     
    78     CREATE_MAP_REGISTRIES;
    79     CREATE_MAPS(ArrayMapFactory);
    80   public:
    81 
    82     ListGraph() : nodes(), first_node(-1),
    83 		  first_free_node(-1), edges(), first_free_edge(-1) {}
    84     ListGraph(const ListGraph &_g) : nodes(_g.nodes), first_node(_g.first_node),
    85 				     first_free_node(_g.first_free_node),
    86 				     edges(_g.edges),
    87 				     first_free_edge(_g.first_free_edge) {}
    88     
    89 
    90     int nodeNum() const { return nodes.size(); }  //FIXME: What is this?
    91     int edgeNum() const { return edges.size(); }  //FIXME: What is this?
    92 
    93     ///Set the expected number of edges
    94 
    95     ///With this function, it is possible to set the expected number of edges.
    96     ///The use of this fasten the building of the graph and makes
    97     ///it possible to avoid the superfluous memory allocation.
    98     void reserveEdge(int n) { edges.reserve(n); };
    99     
   100     ///\bug This function does something different than
   101     ///its name would suggests...
   102     int maxNodeId() const { return nodes.size(); }  //FIXME: What is this?
   103     ///\bug This function does something different than
   104     ///its name would suggests...
   105     int maxEdgeId() const { return edges.size(); }  //FIXME: What is this?
   106 
   107     Node tail(Edge e) const { return edges[e.n].tail; }
   108     Node head(Edge e) const { return edges[e.n].head; }
   109 
   110     Node aNode(OutEdgeIt e) const { return edges[e.n].tail; }
   111     Node aNode(InEdgeIt e) const { return edges[e.n].head; }
   112 
   113     Node bNode(OutEdgeIt e) const { return edges[e.n].head; }
   114     Node bNode(InEdgeIt e) const { return edges[e.n].tail; }
   115 
   116     NodeIt& first(NodeIt& v) const { 
   117       v=NodeIt(*this); return v; }
   118     EdgeIt& first(EdgeIt& e) const { 
   119       e=EdgeIt(*this); return e; }
   120     OutEdgeIt& first(OutEdgeIt& e, const Node v) const { 
   121       e=OutEdgeIt(*this,v); return e; }
   122     InEdgeIt& first(InEdgeIt& e, const Node v) const { 
   123       e=InEdgeIt(*this,v); return e; }
   124 
   125 //     template< typename It >
   126 //     It first() const { It e; first(e); return e; }
   127 
   128 //     template< typename It >
   129 //     It first(Node v) const { It e; first(e,v); return e; }
   130 
   131     bool valid(Edge e) const { return e.n!=-1; }
   132     bool valid(Node n) const { return n.n!=-1; }
   133     
   134     void setInvalid(Edge &e) { e.n=-1; }
   135     void setInvalid(Node &n) { n.n=-1; }
   136     
   137     template <typename It> It getNext(It it) const
   138     { It tmp(it); return next(tmp); }
   139 
   140     NodeIt& next(NodeIt& it) const { 
   141       it.n=nodes[it.n].next; 
   142       return it; 
   143     }
   144     OutEdgeIt& next(OutEdgeIt& it) const
   145     { it.n=edges[it.n].next_out; return it; }
   146     InEdgeIt& next(InEdgeIt& it) const
   147     { it.n=edges[it.n].next_in; return it; }
   148     EdgeIt& next(EdgeIt& it) const {
   149       if(edges[it.n].next_in!=-1) { 
   150 	it.n=edges[it.n].next_in;
   151       }
   152       else {
   153 	int n;
   154 	for(n=nodes[edges[it.n].head].next;
   155 	    n!=-1 && nodes[n].first_in == -1;
   156 	    n = nodes[n].next) ;
   157 	it.n = (n==-1)?-1:nodes[n].first_in;
   158       }
   159       return it;
   160     }
   161 
   162     int id(Node v) const { return v.n; }
   163     int id(Edge e) const { return e.n; }
   164 
   165     /// Adds a new node to the graph.
   166 
   167     /// \todo It adds the nodes in a reversed order.
   168     /// (i.e. the lastly added node becomes the first.)
   169     Node addNode() {
   170       int n;
   171       
   172       if(first_free_node==-1)
   173 	{
   174 	  n = nodes.size();
   175 	  nodes.push_back(NodeT());
   176 	}
   177       else {
   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       
   189       Node nn; nn.n=n;
   190 
   191       //Update dynamic maps
   192       node_maps.add(nn);
   193 
   194       return nn;
   195     }
   196     
   197     Edge addEdge(Node u, Node v) {
   198       int n;
   199       
   200       if(first_free_edge==-1)
   201 	{
   202 	  n = edges.size();
   203 	  edges.push_back(EdgeT());
   204 	}
   205       else {
   206 	n = first_free_edge;
   207 	first_free_edge = edges[n].next_in;
   208       }
   209       
   210       edges[n].tail = u.n; edges[n].head = v.n;
   211 
   212       edges[n].next_out = nodes[u.n].first_out;
   213       if(nodes[u.n].first_out != -1) edges[nodes[u.n].first_out].prev_out = n;
   214       edges[n].next_in = nodes[v.n].first_in;
   215       if(nodes[v.n].first_in != -1) edges[nodes[v.n].first_in].prev_in = n;
   216       edges[n].prev_in = edges[n].prev_out = -1;
   217 	
   218       nodes[u.n].first_out = nodes[v.n].first_in = n;
   219 
   220       Edge e; e.n=n;
   221 
   222       //Update dynamic maps
   223       edge_maps.add(e);
   224 
   225       return e;
   226     }
   227 
   228   private:
   229     void eraseEdge(int n) {
   230       
   231       if(edges[n].next_in!=-1)
   232 	edges[edges[n].next_in].prev_in = edges[n].prev_in;
   233       if(edges[n].prev_in!=-1)
   234 	edges[edges[n].prev_in].next_in = edges[n].next_in;
   235       else nodes[edges[n].head].first_in = edges[n].next_in;
   236       
   237       if(edges[n].next_out!=-1)
   238 	edges[edges[n].next_out].prev_out = edges[n].prev_out;
   239       if(edges[n].prev_out!=-1)
   240 	edges[edges[n].prev_out].next_out = edges[n].next_out;
   241       else nodes[edges[n].tail].first_out = edges[n].next_out;
   242       
   243       edges[n].next_in = first_free_edge;
   244       first_free_edge = n;      
   245 
   246       //Update dynamic maps
   247       Edge e; e.n=n;
   248     }
   249       
   250   public:
   251 
   252     void erase(Node nn) {
   253       int n=nn.n;
   254       
   255       int m;
   256       while((m=nodes[n].first_in)!=-1) eraseEdge(m);
   257       while((m=nodes[n].first_out)!=-1) eraseEdge(m);
   258 
   259       if(nodes[n].next != -1) nodes[nodes[n].next].prev = nodes[n].prev;
   260       if(nodes[n].prev != -1) nodes[nodes[n].prev].next = nodes[n].next;
   261       else first_node = nodes[n].next;
   262       
   263       nodes[n].next = first_free_node;
   264       first_free_node = n;
   265 
   266       //Update dynamic maps
   267       node_maps.erase(nn);
   268      }
   269     
   270     void erase(Edge e) { 
   271       edge_maps.erase(e);
   272       eraseEdge(e.n); 
   273     }
   274 
   275     ///\bug Dynamic maps must be updated!
   276     ///
   277     void clear() {
   278       nodes.clear();edges.clear();
   279       first_node=first_free_node=first_free_edge=-1;
   280     }
   281 
   282     class Node {
   283       friend class ListGraph;
   284       template <typename T> friend class NodeMap;
   285        
   286       friend class Edge;
   287       friend class OutEdgeIt;
   288       friend class InEdgeIt;
   289       friend class SymEdge;
   290 
   291     protected:
   292       int n;
   293       friend int ListGraph::id(Node v) const; 
   294       Node(int nn) {n=nn;}
   295     public:
   296       Node() {}
   297       Node (Invalid) { n=-1; }
   298       bool operator==(const Node i) const {return n==i.n;}
   299       bool operator!=(const Node i) const {return n!=i.n;}
   300       bool operator<(const Node i) const {return n<i.n;}
   301     };
   302     
   303     class NodeIt : public Node {
   304       friend class ListGraph;
   305     public:
   306       NodeIt() : Node() { }
   307       NodeIt(Invalid i) : Node(i) { }
   308       NodeIt(const ListGraph& G) : Node(G.first_node) { }
   309       ///\todo Undocumented conversion Node -\> NodeIt.
   310       NodeIt(const ListGraph& G, const Node &n) : Node(n) { }
   311     };
   312 
   313     class Edge {
   314       friend class ListGraph;
   315       template <typename T> friend class EdgeMap;
   316 
   317       //template <typename T> friend class SymListGraph::SymEdgeMap;      
   318       //friend Edge SymListGraph::opposite(Edge) const;
   319       
   320       friend class Node;
   321       friend class NodeIt;
   322     protected:
   323       int n;
   324       friend int ListGraph::id(Edge e) const;
   325 
   326       Edge(int nn) {n=nn;}
   327     public:
   328       Edge() { }
   329       Edge (Invalid) { n=-1; }
   330       bool operator==(const Edge i) const {return n==i.n;}
   331       bool operator!=(const Edge i) const {return n!=i.n;}
   332       bool operator<(const Edge i) const {return n<i.n;}
   333       ///\bug This is a workaround until somebody tells me how to
   334       ///make class \c SymListGraph::SymEdgeMap friend of Edge
   335       int &idref() {return n;}
   336       const int &idref() const {return n;}
   337     };
   338     
   339     class EdgeIt : public Edge {
   340       friend class ListGraph;
   341     public:
   342       EdgeIt(const ListGraph& G) : Edge() {
   343       	int m;
   344 	for(m=G.first_node;
   345 	    m!=-1 && G.nodes[m].first_in == -1; m = G.nodes[m].next);
   346 	n = (m==-1)?-1:G.nodes[m].first_in;
   347       }
   348       EdgeIt (Invalid i) : Edge(i) { }
   349       EdgeIt() : Edge() { }
   350       ///\bug This is a workaround until somebody tells me how to
   351       ///make class \c SymListGraph::SymEdgeMap friend of Edge
   352       int &idref() {return n;}
   353     };
   354     
   355     class OutEdgeIt : public Edge {
   356       friend class ListGraph;
   357     public: 
   358       OutEdgeIt() : Edge() { }
   359       OutEdgeIt (Invalid i) : Edge(i) { }
   360 
   361       OutEdgeIt(const ListGraph& G,const Node v)
   362 	: Edge(G.nodes[v.n].first_out) {}
   363     };
   364     
   365     class InEdgeIt : public Edge {
   366       friend class ListGraph;
   367     public: 
   368       InEdgeIt() : Edge() { }
   369       InEdgeIt (Invalid i) : Edge(i) { }
   370       InEdgeIt(const ListGraph& G,Node v) :Edge(G.nodes[v.n].first_in) {}
   371     };
   372 
   373   };
   374 
   375   ///Graph for bidirectional edges.
   376 
   377   ///The purpose of this graph structure is to handle graphs
   378   ///having bidirectional edges. Here the function \c addEdge(u,v) adds a pair
   379   ///of oppositely directed edges.
   380   ///There is a new edge map type called
   381   ///\ref SymListGraph::SymEdgeMap "SymEdgeMap"
   382   ///that complements this
   383   ///feature by
   384   ///storing shared values for the edge pairs. The usual
   385   ///\ref GraphSkeleton::EdgeMap "EdgeMap"
   386   ///can be used
   387   ///as well.
   388   ///
   389   ///The oppositely directed edge can also be obtained easily
   390   ///using \ref opposite.
   391   ///
   392   ///Here erase(Edge) deletes a pair of edges.
   393   ///
   394   ///\todo this date structure need some reconsiderations. Maybe it
   395   ///should be implemented independently from ListGraph.
   396 
   397 }
   398 
   399 #endif //HUGO_LIST_GRAPH_H