# HG changeset patch # User alpar # Date 1118310596 0 # Node ID 2ee881cf30a8392581b9b0f6f66e23a2846a13b7 # Parent 7a483c1d38b502e2d64210be1c27ad166685b4da - InDegMap fixed - OutDegMap added - test cases added for them both diff -r 7a483c1d38b5 -r 2ee881cf30a8 lemon/graph_utils.h --- a/lemon/graph_utils.h Thu Jun 09 09:49:48 2005 +0000 +++ b/lemon/graph_utils.h Thu Jun 09 09:49:56 2005 +0000 @@ -24,6 +24,7 @@ #include #include #include +#include ///\ingroup gutils ///\file @@ -855,21 +856,20 @@ - /* ***************************************************************** */ + /// Map of the node in-degrees. - /// Provides O(1) time node-degree queries. - - ///\todo Undocumented + ///This map returns the in-degree of a node. Ones it is constructed, + ///the degrees are stored in a standard NodeMap, so each query is done + ///in constant time. On the other hand, the values updates automatically + ///whenever the graph changes. /// + ///\sa OutDegMap template class InDegMap : - protected _Graph::template AlterationNotifier:: - ObserverBase, - protected _Graph::template AlterationNotifier:: - ObserverBase + protected _Graph::template NodeMap, + protected AlterationNotifier::ObserverBase { - typename _Graph::template NodeMap deg; - const _Graph* graph; + const _Graph& graph; public: typedef int Value; typedef typename _Graph::Node Key; @@ -877,44 +877,113 @@ /// \brief Constructor. /// /// Constructor for creating in-degree map. - InDegMap(const _Graph& _graph) : graph(_graph), deg(graph,0) + InDegMap(const _Graph& _graph) : + _Graph::NodeMap(_graph,0), + graph(_graph) { - typename _Graph::template AlterationNotifier - ::ObserverBase::attach(graph->getNotifier(typename _Graph::Node())); - typename _Graph::template AlterationNotifier - ::ObserverBase::attach(graph->getNotifier(typename _Graph::Edge())); + AlterationNotifier + ::ObserverBase::attach(graph.getNotifier(typename _Graph::Edge())); for(typename _Graph::NodeIt n(graph);n!=INVALID;++n) for(typename _Graph::InEdgeIt e(graph,n);e!=INVALID;++e) - deg[e]++; + _Graph::template NodeMap::operator[](graph.target(e))++; } - ~InDegMap() + virtual ~InDegMap() { - typename _Graph::template AlterationNotifier:: - ObserverBase::detach(); - typename _Graph::template AlterationNotifier:: + AlterationNotifier:: ObserverBase::detach(); } - /// Gives back the in degree of a Node. - int operator[](const Key& k) const { return deg[k];} + /// Gives back the in-degree of a Node. + int operator[](const Key& k) const { + return _Graph::template NodeMap::operator[](k); + } protected: virtual void add(const typename _Graph::Node& n) { - ///\bug Which 'add' comes before to other? - deg[n]=0; + _Graph::template NodeMap::add(n); + _Graph::template NodeMap::operator[](n)=0; } - virtual void erase(const typename _Graph::Node&) + virtual void erase(const typename _Graph::Node&n) { + _Graph::template NodeMap::erase(n); } virtual void add(const typename _Graph::Edge& e) { - deg[graph.target(e)]++; + _Graph::template NodeMap::operator[](graph.target(e))++; } virtual void erase(const typename _Graph::Edge& e) { - deg[graph.target(e)]--; + _Graph::template NodeMap::operator[](graph.target(e))--; } + virtual void build() {} + virtual void clear() {} + + }; + + + /// Map of the node out-degrees. + + ///This map returns the out-degree of a node. One it is constructed, + ///the degrees are stored in a standard NodeMap, so each query is done + ///in constant time. On the other hand, the values updates automatically + ///whenever the graph changes. + /// + ///\sa OutDegMap + template + class OutDegMap : + protected _Graph::template NodeMap, + protected AlterationNotifier::ObserverBase + { + const _Graph& graph; + public: + typedef int Value; + typedef typename _Graph::Node Key; + + /// \brief Constructor. + /// + /// Constructor for creating out-degree map. + OutDegMap(const _Graph& _graph) : + _Graph::NodeMap(_graph,0), + graph(_graph) + { + AlterationNotifier + ::ObserverBase::attach(graph.getNotifier(typename _Graph::Edge())); + + for(typename _Graph::NodeIt n(graph);n!=INVALID;++n) + for(typename _Graph::InEdgeIt e(graph,n);e!=INVALID;++e) + _Graph::template NodeMap::operator[](graph.source(e))++; + } + + ~OutDegMap() + { + AlterationNotifier:: + ObserverBase::detach(); + } + + /// Gives back the in-degree of a Node. + int operator[](const Key& k) const { + return _Graph::template NodeMap::operator[](k); + } + + protected: + virtual void add(const typename _Graph::Node& n) { + _Graph::template NodeMap::add(n); + _Graph::template NodeMap::operator[](n)=0; + } + virtual void erase(const typename _Graph::Node&n) + { + _Graph::template NodeMap::erase(n); + } + virtual void add(const typename _Graph::Edge& e) { + _Graph::template NodeMap::operator[](graph.source(e))++; + } + virtual void erase(const typename _Graph::Edge& e) { + _Graph::template NodeMap::operator[](graph.source(e))--; + } + + virtual void build() {} + virtual void clear() {} }; diff -r 7a483c1d38b5 -r 2ee881cf30a8 test/graph_utils_test.cc --- a/test/graph_utils_test.cc Thu Jun 09 09:49:48 2005 +0000 +++ b/test/graph_utils_test.cc Thu Jun 09 09:49:56 2005 +0000 @@ -15,6 +15,36 @@ using namespace lemon; +template +void checkSnapDeg() +{ + Graph g; + typename Graph::Node n1=g.addNode(); + typename Graph::Node n2=g.addNode(); + + InDegMap ind(g); + + g.addEdge(n1,n2); + + typename Graph::SnapShot snap(g); + + OutDegMap outd(g); + + check(ind[n1]==0 && ind[n2]==1, "Wrong InDegMap value."); + check(outd[n1]==1 && outd[n2]==0, "Wrong OutDegMap value."); + + g.addEdge(n1,n2); + g.addEdge(n2,n1); + + check(ind[n1]==1 && ind[n2]==2, "Wrong InDegMap value."); + check(outd[n1]==2 && outd[n2]==1, "Wrong OutDegMap value."); + + snap.restore(); + + check(ind[n1]==0 && ind[n2]==1, "Wrong InDegMap value."); + check(outd[n1]==1 && outd[n2]==0, "Wrong OutDegMap value."); + +} int main() { ///\file @@ -31,6 +61,13 @@ check(countEdges(fg) == num*num, "FullGraph: wrong edge number."); } + //check In/OutDegMap (and SnapShot feature) + + checkSnapDeg(); + checkSnapDeg(); + + + ///Everything is OK std::cout << __FILE__ ": All tests passed.\n"; return 0;