[Lemon-commits] [lemon_svn] alpar: r528 - hugo/trunk/src/work/alpar

Lemon SVN svn at lemon.cs.elte.hu
Mon Nov 6 20:39:59 CET 2006


Author: alpar
Date: Sun Apr 25 18:53:38 2004
New Revision: 528

Added:
   hugo/trunk/src/work/alpar/list_graph_demo.cc
Modified:
   hugo/trunk/src/work/alpar/list_graph.h

Log:
I hope it works. The 'erase' functions hasn't been tested yet.


Modified: hugo/trunk/src/work/alpar/list_graph.h
==============================================================================
--- hugo/trunk/src/work/alpar/list_graph.h	(original)
+++ hugo/trunk/src/work/alpar/list_graph.h	Sun Apr 25 18:53:38 2004
@@ -4,7 +4,7 @@
 #define HUGO_SMART_GRAPH_H
 
 ///\file
-///\brief SmartGraph and SymSmartGraph classes.
+///\brief ListGraph and SymListGraph classes.
 
 #include <vector>
 #include <limits.h>
@@ -13,52 +13,63 @@
 
 namespace hugo {
 
-  class SymSmartGraph;
+  class SymListGraph;
 
   ///A smart graph class.
 
-  ///This is a simple and fast graph implementation.
-  ///It is also quite memory efficient, but at the price
-  ///that <b> it does not support node and edge deletion</b>.
+  ///This is a simple and fast erasable graph implementation.
+  ///
   ///It conforms to the graph interface documented under
   ///the description of \ref GraphSkeleton.
   ///\sa \ref GraphSkeleton.
-  class SmartGraph {
+  class ListGraph {
 
+    //Nodes are double linked.
+    //The free nodes are only single linked using the "next" field.
     struct NodeT 
     {
-      int first_in,first_out;      
-      NodeT() : first_in(-1), first_out(-1) {}
+      int first_in,first_out;
+      int prev, next;
+      //      NodeT() {}
     };
+    //Edges are double linked.
+    //The free edges are only single linked using the "next_in" field.
     struct EdgeT 
     {
-      int head, tail, next_in, next_out;      
+      int head, tail;
+      int prev_in, prev_out;
+      int next_in, next_out;
       //FIXME: is this necessary?
-      EdgeT() : next_in(-1), next_out(-1) {}  
+      //      EdgeT() : next_in(-1), next_out(-1) prev_in(-1), prev_out(-1) {}  
     };
 
     std::vector<NodeT> nodes;
-
+    //The first node
+    int first_node;
+    //The first free node
+    int first_free_node;
     std::vector<EdgeT> edges;
+    //The first free edge
+    int first_free_edge;
     
-    protected:
+  protected:
     
     template <typename Key> class DynMapBase
     {
     protected:
-      const SmartGraph* G; 
+      const ListGraph* G; 
     public:
       virtual void add(const Key k) = NULL;
       virtual void erase(const Key k) = NULL;
-      DynMapBase(const SmartGraph &_G) : G(&_G) {}
+      DynMapBase(const ListGraph &_G) : G(&_G) {}
       virtual ~DynMapBase() {}
-      friend class SmartGraph;
+      friend class ListGraph;
     };
     
   public:
     template <typename T> class EdgeMap;
     template <typename T> class EdgeMap;
-
+    
     class Node;
     class Edge;
 
@@ -84,10 +95,14 @@
     
   public:
 
-    SmartGraph() : nodes(), edges() { }
-    SmartGraph(const SmartGraph &_g) : nodes(_g.nodes), edges(_g.edges) { }
+    ListGraph() : nodes(), first_node(-1),
+		  first_free_node(-1), edges(), first_free_edge(-1) {}
+    ListGraph(const ListGraph &_g) : nodes(_g.nodes), first_node(_g.first_node),
+				     first_free_node(_g.first_free_node),
+				     edges(_g.edges),
+				     first_free_edge(_g.first_free_edge) {}
     
-    ~SmartGraph()
+    ~ListGraph()
     {
       for(std::vector<DynMapBase<Node> * >::iterator i=dyn_node_maps.begin();
 	  i!=dyn_node_maps.end(); ++i) (**i).G=NULL;
@@ -139,45 +154,151 @@
     { It tmp(it); return next(tmp); }
 
     NodeIt& next(NodeIt& it) const { 
-      it.n=(it.n+2)%(nodes.size()+1)-1; 
+      it.n=nodes[it.n].next; 
       return it; 
     }
     OutEdgeIt& next(OutEdgeIt& it) const
     { it.n=edges[it.n].next_out; return it; }
     InEdgeIt& next(InEdgeIt& it) const
     { it.n=edges[it.n].next_in; return it; }
-    EdgeIt& next(EdgeIt& it) const { --it.n; return it; }
+    EdgeIt& next(EdgeIt& it) const {
+      if(edges[it.n].next_in!=-1) { 
+	it.n=edges[it.n].next_in;
+      }
+      else {
+	int n;
+	for(n=nodes[edges[it.n].head].next;
+	    n!=-1 && nodes[n].first_in == -1;
+	    n = nodes[n].next) ;
+	it.n = (n==-1)?-1:nodes[n].first_in;
+      }
+      return it;
+    }
 
     int id(Node v) const { return v.n; }
     int id(Edge e) const { return e.n; }
 
+    /// Adds a new node to the graph.
+
+    /// \todo It adds the nodes in a reversed order.
+    /// (i.e. the lastly added node becomes the first.)
     Node addNode() {
-      Node n; n.n=nodes.size();
-      nodes.push_back(NodeT()); //FIXME: Hmmm...
+      int n;
+      
+      if(first_free_node==-1)
+	{
+	  n = nodes.size();
+	  nodes.push_back(NodeT());
+	}
+      else {
+	n = first_free_node;
+	first_free_node = nodes[n].next;
+      }
+      
+      nodes[n].next = first_node;
+      if(first_node != -1) nodes[first_node].prev = n;
+      first_node = n;
+      nodes[n].prev = -1;
+      
+      nodes[n].first_in = nodes[n].first_out = -1;
+      
+      Node nn; nn.n=n;
 
+      //Update dynamic maps
       for(std::vector<DynMapBase<Node> * >::iterator i=dyn_node_maps.begin();
-	  i!=dyn_node_maps.end(); ++i) (**i).add(n.n);
+	  i!=dyn_node_maps.end(); ++i) (**i).add(nn);
 
-      return n;
+      return nn;
     }
     
     Edge addEdge(Node u, Node v) {
-      Edge e; e.n=edges.size(); edges.push_back(EdgeT()); //FIXME: Hmmm...
-      edges[e.n].tail=u.n; edges[e.n].head=v.n;
-      edges[e.n].next_out=nodes[u.n].first_out;
-      edges[e.n].next_in=nodes[v.n].first_in;
-      nodes[u.n].first_out=nodes[v.n].first_in=e.n;
+      int n;
+      
+      if(first_free_edge==-1)
+	{
+	  n = edges.size();
+	  edges.push_back(EdgeT());
+	}
+      else {
+	n = first_free_edge;
+	first_free_edge = edges[n].next_in;
+      }
+      
+      edges[n].tail = u.n; edges[n].head = v.n;
+
+      edges[n].next_out = nodes[u.n].first_out;
+      if(nodes[u.n].first_out != -1) edges[nodes[u.n].first_out].prev_out = n;
+      edges[n].next_in = nodes[v.n].first_in;
+      if(nodes[v.n].first_in != -1) edges[nodes[v.n].first_in].prev_in = n;
+      edges[n].prev_in = edges[n].prev_out = -1;
+	
+      nodes[u.n].first_out = nodes[v.n].first_in = n;
+
+      Edge e; e.n=n;
 
+      //Update dynamic maps
       for(std::vector<DynMapBase<Edge> * >::iterator i=dyn_edge_maps.begin();
 	  i!=dyn_edge_maps.end(); ++i) (**i).add(e);
 
       return e;
     }
 
-    void clear() {nodes.clear();edges.clear();}
+  private:
+    void eraseEdge(int n) {
+      
+      if(edges[n].next_in!=-1)
+	edges[edges[n].next_in].prev_in = edges[n].prev_in;
+      if(edges[n].prev_in!=-1)
+	edges[edges[n].prev_in].next_in = edges[n].next_in;
+      else nodes[edges[n].head].first_in = edges[n].next_in;
+      
+      if(edges[n].next_out!=-1)
+	edges[edges[n].next_out].prev_out = edges[n].prev_out;
+      if(edges[n].prev_out!=-1)
+	edges[edges[n].prev_out].next_out = edges[n].next_out;
+      else nodes[edges[n].tail].first_out = edges[n].next_out;
+      
+      edges[n].next_in = first_free_edge;
+      first_free_edge = -1;      
+
+      //Update dynamic maps
+      Edge e; e.n=n;
+      for(std::vector<DynMapBase<Edge> * >::iterator i=dyn_edge_maps.begin();
+	  i!=dyn_edge_maps.end(); ++i) (**i).erase(e);
+    }
+      
+  public:
+
+    void erase(Node nn) {
+      int n=nn.n;
+      
+      int m;
+      while((m=nodes[n].first_in)!=-1) eraseEdge(m);
+      while((m=nodes[n].first_out)!=-1) eraseEdge(m);
+
+      if(nodes[n].next != -1) nodes[nodes[n].next].prev = nodes[n].prev;
+      if(nodes[n].prev != -1) nodes[nodes[n].prev].next = nodes[n].next;
+      else first_node = nodes[n].next;
+      
+      nodes[n].next = first_free_node;
+      first_free_node = n;
+
+      //Update dynamic maps
+      for(std::vector<DynMapBase<Node> * >::iterator i=dyn_node_maps.begin();
+	  i!=dyn_node_maps.end(); ++i) (**i).erase(nn);
+    }
+    
+    void erase(Edge e) { eraseEdge(e.n); }
+
+    ///\bug Dynamic maps must be updated!
+    ///
+    void clear() {
+      nodes.clear();edges.clear();
+      first_node=first_free_node=first_free_edge=-1;
+    }
 
     class Node {
-      friend class SmartGraph;
+      friend class ListGraph;
       template <typename T> friend class NodeMap;
       
       friend class Edge;
@@ -187,7 +308,7 @@
 
     protected:
       int n;
-      friend int SmartGraph::id(Node v) const; 
+      friend int ListGraph::id(Node v) const; 
       Node(int nn) {n=nn;}
     public:
       Node() {}
@@ -198,24 +319,24 @@
     };
     
     class NodeIt : public Node {
-      friend class SmartGraph;
+      friend class ListGraph;
     public:
-      NodeIt(const SmartGraph& G) : Node(G.nodes.size()?0:-1) { }
+      NodeIt(const ListGraph& G) : Node(G.first_node) { }
       NodeIt() : Node() { }
     };
 
     class Edge {
-      friend class SmartGraph;
+      friend class ListGraph;
       template <typename T> friend class EdgeMap;
 
-      //template <typename T> friend class SymSmartGraph::SymEdgeMap;      
-      //friend Edge SymSmartGraph::opposite(Edge) const;
+      //template <typename T> friend class SymListGraph::SymEdgeMap;      
+      //friend Edge SymListGraph::opposite(Edge) const;
       
       friend class Node;
       friend class NodeIt;
     protected:
       int n;
-      friend int SmartGraph::id(Edge e) const;
+      friend int ListGraph::id(Edge e) const;
 
       Edge(int nn) {n=nn;}
     public:
@@ -225,38 +346,43 @@
       bool operator!=(const Edge i) const {return n!=i.n;}
       bool operator<(const Edge i) const {return n<i.n;}
       ///\bug This is a workaround until somebody tells me how to
-      ///make class \c SymSmartGraph::SymEdgeMap friend of Edge
+      ///make class \c SymListGraph::SymEdgeMap friend of Edge
       int &idref() {return n;}
       const int &idref() const {return n;}
     };
     
     class EdgeIt : public Edge {
-      friend class SmartGraph;
+      friend class ListGraph;
     public:
-      EdgeIt(const SmartGraph& G) : Edge(G.edges.size()-1) { }
+      EdgeIt(const ListGraph& G) : Edge() {
+      	int m;
+	for(m=G.first_node;
+	    m!=-1 && G.nodes[m].first_in == -1; m = G.nodes[m].next);
+	n = (m==-1)?-1:G.nodes[m].first_in;
+      }
       EdgeIt (Invalid i) : Edge(i) { }
       EdgeIt() : Edge() { }
       ///\bug This is a workaround until somebody tells me how to
-      ///make class \c SymSmartGraph::SymEdgeMap friend of Edge
+      ///make class \c SymListGraph::SymEdgeMap friend of Edge
       int &idref() {return n;}
     };
     
     class OutEdgeIt : public Edge {
-      friend class SmartGraph;
+      friend class ListGraph;
     public: 
       OutEdgeIt() : Edge() { }
       OutEdgeIt (Invalid i) : Edge(i) { }
 
-      OutEdgeIt(const SmartGraph& G,const Node v)
+      OutEdgeIt(const ListGraph& G,const Node v)
 	: Edge(G.nodes[v.n].first_out) {}
     };
     
     class InEdgeIt : public Edge {
-      friend class SmartGraph;
+      friend class ListGraph;
     public: 
       InEdgeIt() : Edge() { }
       InEdgeIt (Invalid i) : Edge(i) { }
-      InEdgeIt(const SmartGraph& G,Node v) :Edge(G.nodes[v.n].first_in){}
+      InEdgeIt(const ListGraph& G,Node v) :Edge(G.nodes[v.n].first_in){}
     };
 
     template <typename T> class NodeMap : public DynMapBase<Node>
@@ -267,12 +393,12 @@
       typedef T ValueType;
       typedef Node KeyType;
 
-      NodeMap(const SmartGraph &_G) :
+      NodeMap(const ListGraph &_G) :
 	DynMapBase<Node>(_G), container(_G.maxNodeId())
       {
 	G->dyn_node_maps.push_back(this);
       }
-      NodeMap(const SmartGraph &_G,const T &t) :
+      NodeMap(const ListGraph &_G,const T &t) :
 	DynMapBase<Node>(_G), container(_G.maxNodeId(),t)
       {
 	G->dyn_node_maps.push_back(this);
@@ -357,14 +483,14 @@
       typedef T ValueType;
       typedef Edge KeyType;
 
-      EdgeMap(const SmartGraph &_G) :
+      EdgeMap(const ListGraph &_G) :
 	DynMapBase<Edge>(_G), container(_G.maxEdgeId())
       {
 	//FIXME: What if there are empty Id's?
 	//FIXME: Can I use 'this' in a constructor?
 	G->dyn_edge_maps.push_back(this);
       }
-      EdgeMap(const SmartGraph &_G,const T &t) :
+      EdgeMap(const ListGraph &_G,const T &t) :
 	DynMapBase<Edge>(_G), container(_G.maxEdgeId(),t)
       {
 	G->dyn_edge_maps.push_back(this);
@@ -446,7 +572,7 @@
   ///having bidirectional edges. Here the function \c addEdge(u,v) adds a pair
   ///of oppositely directed edges.
   ///There is a new edge map type called
-  ///\ref SymSmartGraph::SymEdgeMap "SymEdgeMap"
+  ///\ref SymListGraph::SymEdgeMap "SymEdgeMap"
   ///that complements this
   ///feature by
   ///storing shared values for the edge pairs. The usual
@@ -456,25 +582,29 @@
   ///
   ///The oppositely directed edge can also be obtained easily
   ///using \ref opposite.
-  ///\warning It shares the similarity with \ref SmartGraph that
-  ///it is not possible to delete edges or nodes from the graph.
-  //\sa \ref SmartGraph.
+  ///
+  ///Here erase(Edge) deletes a pair of edges.
+  ///
+  ///\todo this date structure need some reconsiderations. Maybe it
+  ///should be implemented independently from ListGraph.
 
-  class SymSmartGraph : public SmartGraph
+  class SymListGraph : public ListGraph
   {
   public:
     template<typename T> class SymEdgeMap;
     template<typename T> friend class SymEdgeMap;
 
-    SymSmartGraph() : SmartGraph() { }
-    SymSmartGraph(const SmartGraph &_g) : SmartGraph(_g) { }
+    SymListGraph() : ListGraph() { }
+    SymListGraph(const ListGraph &_g) : ListGraph(_g) { }
+    ///Adds a pair of oppositely directed edges to the graph.
     Edge addEdge(Node u, Node v)
     {
-      Edge e = SmartGraph::addEdge(u,v);
-      SmartGraph::addEdge(v,u);
+      Edge e = ListGraph::addEdge(u,v);
+      ListGraph::addEdge(v,u);
       return e;
     }
 
+    void erase(Node n) { ListGraph::erase(n); }
     ///The oppositely directed edge.
 
     ///Returns the oppositely directed
@@ -486,6 +616,12 @@
       return f;
     }
     
+    ///Removes a pair of oppositely directed edges to the graph.
+    void erase(Edge e) {
+      ListGraph::erase(opposite(e));
+      ListGraph::erase(e);
+    }
+    
     ///Common data storage for the edge pairs.
 
     ///This map makes it possible to store data shared by the oppositely
@@ -498,12 +634,12 @@
       typedef T ValueType;
       typedef Edge KeyType;
 
-      SymEdgeMap(const SymSmartGraph &_G) :
+      SymEdgeMap(const SymListGraph &_G) :
 	DynMapBase<Edge>(_G), container(_G.maxEdgeId()/2)
       {
-	static_cast<const SymSmartGraph*>(G)->dyn_edge_maps.push_back(this);
+	static_cast<const SymListGraph*>(G)->dyn_edge_maps.push_back(this);
       }
-      SymEdgeMap(const SymSmartGraph &_G,const T &t) :
+      SymEdgeMap(const SymListGraph &_G,const T &t) :
 	DynMapBase<Edge>(_G), container(_G.maxEdgeId()/2,t)
       {
 	G->dyn_edge_maps.push_back(this);
@@ -535,14 +671,14 @@
       {
 	if(G) {
 	  std::vector<DynMapBase<Edge>* >::iterator i;
-	  for(i=static_cast<const SymSmartGraph*>(G)->dyn_edge_maps.begin();
-	      i!=static_cast<const SymSmartGraph*>(G)->dyn_edge_maps.end()
+	  for(i=static_cast<const SymListGraph*>(G)->dyn_edge_maps.begin();
+	      i!=static_cast<const SymListGraph*>(G)->dyn_edge_maps.end()
 		&& *i!=this; ++i) ;
 	  //if(*i==this) G->dyn_edge_maps.erase(i); //Way too slow...
 	  //A better way to do that: (Is this really important?)
 	  if(*i==this) {
-	    *i=static_cast<const SymSmartGraph*>(G)->dyn_edge_maps.back();
-	    static_cast<const SymSmartGraph*>(G)->dyn_edge_maps.pop_back();
+	    *i=static_cast<const SymListGraph*>(G)->dyn_edge_maps.back();
+	    static_cast<const SymListGraph*>(G)->dyn_edge_maps.pop_back();
 	  }
 	}
       }

Added: hugo/trunk/src/work/alpar/list_graph_demo.cc
==============================================================================
--- (empty file)
+++ hugo/trunk/src/work/alpar/list_graph_demo.cc	Sun Apr 25 18:53:38 2004
@@ -0,0 +1,124 @@
+#include<list_graph.h>
+#include<skeletons/graph.h>
+
+#include <iostream>
+#include <vector>
+
+using namespace hugo;
+
+typedef ListGraph Graph;
+//typedef GraphSkeleton Graph;
+
+
+Graph::OutEdgeIt safeFirstOut(const Graph &G, Graph::Node n)
+{
+  return G.valid(n) ? Graph::OutEdgeIt(G,n):INVALID;
+}
+
+int main()
+{
+
+  typedef Graph::Edge Edge;
+  typedef Graph::InEdgeIt InEdgeIt;
+  typedef Graph::OutEdgeIt OutEdgeIt;
+  typedef Graph::EdgeIt EdgeIt;
+  typedef Graph::Node Node;
+  typedef Graph::NodeIt NodeIt;
+  
+  Graph G;
+  
+  {
+    NodeIt n;
+
+    for(int i=0;i<10;i++) G.addNode();
+    for(G.first(n);G.valid(n);G.next(n)) 
+      for(NodeIt m(G);m!=INVALID;G.next(m)) 
+	if(n!=m) G.addEdge(n,m);
+    
+    OutEdgeIt e = safeFirstOut(G,n);
+    OutEdgeIt f = safeFirstOut(G,NodeIt(G));
+    
+    
+    InEdgeIt i(INVALID), j;
+    InEdgeIt ii(i);
+    ii=G.first(i,n);
+    ii=G.next(i);
+    
+    OutEdgeIt o(INVALID), oo;
+    OutEdgeIt ooo(oo);
+    oo=G.first(o,n);
+    oo=G.next(o);
+    
+    EdgeIt ei(INVALID), eie;
+    EdgeIt eiee(ei);
+    eie=G.first(ei);
+    eie=G.next(ei);
+    
+    Edge eee(i);
+    eee=o;
+    eee=eie;
+    
+    
+    bool tm;
+    tm = G.valid(n) && G.valid(i) && G.valid(o) && G.valid(ei);
+    
+    std::vector<InEdgeIt> v(10);
+    std::vector<InEdgeIt> w(10,INVALID);
+    
+  }
+  
+  // Test of maps
+
+  G.clear();
+  
+  for(int i=0;i<10;i++) G.addNode();
+  for(NodeIt i(G);G.valid(i);G.next(i)) 
+    for(NodeIt j(G);G.valid(j);G.next(j)) 
+      if(i<j) G.addEdge(i,j);           //The iterators are comparable
+  
+  Graph::NodeMap<int> n(G);
+  int count=0;
+  for(NodeIt i(G);G.valid(i);G.next(i)) n[i]=count++;
+  
+  Graph::NodeMap<int> nn=n;
+  Graph::NodeMap<double> dd=n;
+
+  n = nn;
+  
+  dd = nn;
+  
+  Graph::EdgeMap<int> emap(G);
+
+  // Test of SymListGraph
+  
+  {
+    typedef SymListGraph Graph;
+    typedef Graph::Edge Edge;
+    typedef Graph::InEdgeIt InEdgeIt;
+    typedef Graph::OutEdgeIt OutEdgeIt;
+    typedef Graph::EdgeIt EdgeIt;
+    typedef Graph::Node Node;
+    typedef Graph::NodeIt NodeIt;
+
+    Graph G;
+
+    for(int i=0;i<10;i++) G.addNode();
+    for(NodeIt i(G);G.valid(i);G.next(i)) 
+      for(NodeIt j(G);G.valid(j);G.next(j)) 
+	if(i<j) G.addEdge(i,j);           //The iterators are comparable
+  
+    Graph::EdgeMap<int> em(G);
+    Graph::SymEdgeMap<int> sm(G);
+    for(EdgeIt e(G);G.valid(e);G.next(e)) em[e]=G.id(e);
+    for(EdgeIt e(G);G.valid(e);G.next(e))
+      if(G.tail(e)<G.head(e)) sm[e]=G.id(e);
+    
+    for(EdgeIt e(G);G.valid(e);G.next(e))
+      std::cout << G.id(G.tail(e)) << "->" << G.id(G.head(e))
+		<< ": id=" << G.id(e) << " oppid=" << G.id(G.opposite(e))
+		<< " em=" << em[e]
+		<< " sm=" << sm[e] << "\n";
+    
+  }
+  
+}



More information about the Lemon-commits mailing list