diff -r f2ea4aac9ada -r c94ef40a22ce src/lemon/list_graph.h --- a/src/lemon/list_graph.h Mon Oct 25 13:29:46 2004 +0000 +++ b/src/lemon/list_graph.h Wed Oct 27 22:38:50 2004 +0000 @@ -1,117 +1,87 @@ -/* -*- C++ -*- - * src/lemon/list_graph.h - Part of LEMON, a generic C++ optimization library - * - * Copyright (C) 2004 Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport - * (Egervary Combinatorial Optimization Research Group, EGRES). - * - * Permission to use, modify and distribute this software is granted - * provided that this copyright notice appears in all copies. For - * precise terms see the accompanying LICENSE file. - * - * This software is provided "AS IS" with no warranty of any kind, - * express or implied, and with no claim as to its suitability for any - * purpose. - * - */ +// -*- c++ -*- #ifndef LEMON_LIST_GRAPH_H #define LEMON_LIST_GRAPH_H -///\ingroup graphs -///\file -///\brief ListGraph, SymListGraph, NodeSet and EdgeSet classes. +#include +#include +#include -#include -#include +#include -#include +#include -#include -#include +#include -#include +#include namespace lemon { -/// \addtogroup graphs -/// @{ + class ListGraphBase { - ///A list graph class. - - ///This is a simple and fast erasable graph implementation. - /// - ///It conforms to the - ///\ref skeleton::ErasableGraph "ErasableGraph" concept. - ///\sa skeleton::ErasableGraph. - class ListGraph { - - //Nodes are double linked. - //The free nodes are only single linked using the "next" field. - struct NodeT - { + struct NodeT { int first_in,first_out; int prev, next; }; - //Edges are double linked. - //The free edges are only single linked using the "next_in" field. - struct EdgeT - { + + struct EdgeT { int head, tail; int prev_in, prev_out; int next_in, next_out; }; std::vector nodes; - //The first node + int first_node; - //The first free node + int first_free_node; + std::vector edges; - //The first free edge + int first_free_edge; public: - typedef ListGraph Graph; + typedef ListGraphBase Graph; - class Node; - class Edge; + class Node { + friend class Graph; + protected: - - public: + int id; + Node(int pid) { id = pid;} - class NodeIt; - class EdgeIt; - class OutEdgeIt; - class InEdgeIt; + public: + Node() {} + Node (Invalid) { id = -1; } + bool operator==(const Node& node) const {return id == node.id;} + bool operator!=(const Node& node) const {return id != node.id;} + bool operator<(const Node& node) const {return id < node.id;} + }; - // Create map registries. - CREATE_MAP_REGISTRIES; - // Create node and edge maps. - CREATE_MAPS(ArrayMap); + class Edge { + friend class Graph; + protected: - public: + int id; + Edge(int pid) { id = pid;} - ListGraph() + public: + Edge() {} + Edge (Invalid) { id = -1; } + bool operator==(const Edge& edge) const {return id == edge.id;} + bool operator!=(const Edge& edge) const {return id != edge.id;} + bool operator<(const Edge& edge) const {return id < edge.id;} + }; + + + + ListGraphBase() : 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) {} - /// \bug In the vector can be hole if a node is erased from the graph. - ///Number of nodes. - int nodeNum() const { return nodes.size(); } - ///Number of edges. - int edgeNum() const { return edges.size(); } - - ///Set the expected maximum number of edges. - - ///With this function, it is possible to set the expected number of edges. - ///The use of this fasten the building of the graph and makes ///it possible to avoid the superfluous memory allocation. void reserveEdge(int n) { edges.reserve(n); }; @@ -120,56 +90,75 @@ /// Maximum node ID. ///\sa id(Node) int maxNodeId() const { return nodes.size()-1; } + /// Maximum edge ID. /// Maximum edge ID. ///\sa id(Edge) int maxEdgeId() const { return edges.size()-1; } - Node tail(Edge e) const { return edges[e.n].tail; } - Node head(Edge e) const { return edges[e.n].head; } + Node tail(Edge e) const { return edges[e.id].tail; } + Node head(Edge e) const { return edges[e.id].head; } - NodeIt& first(NodeIt& v) const { - v=NodeIt(*this); return v; } - EdgeIt& first(EdgeIt& e) const { - e=EdgeIt(*this); return e; } - OutEdgeIt& first(OutEdgeIt& e, const Node v) const { - e=OutEdgeIt(*this,v); return e; } - InEdgeIt& first(InEdgeIt& e, const Node v) const { - e=InEdgeIt(*this,v); return e; } - /// Node ID. + void first(Node& node) const { + node.id = first_node; + } + + void next(Node& node) const { + node.id = nodes[node.id].next; + } + + + void first(Edge& e) const { + int n; + for(n = first_node; + n!=-1 && nodes[n].first_in == -1; + n = nodes[n].next); + e.id = (n == -1) ? -1 : nodes[n].first_in; + } + + void next(Edge& edge) const { + if (edges[edge.id].next_in != -1) { + edge.id = edges[edge.id].next_in; + } else { + int n; + for(n = nodes[edges[edge.id].head].next; + n!=-1 && nodes[n].first_in == -1; + n = nodes[n].next); + edge.id = (n == -1) ? -1 : nodes[n].first_in; + } + } + + void firstOut(Edge &e, const Node& v) const { + e.id = nodes[v.id].first_out; + } + void nextOut(Edge &e) const { + e.id=edges[e.id].next_out; + } + + void firstIn(Edge &e, const Node& v) const { + e.id = nodes[v.id].first_in; + } + void nextIn(Edge &e) const { + e.id=edges[e.id].next_in; + } + - /// The ID of a valid Node is a nonnegative integer not greater than - /// \ref maxNodeId(). The range of the ID's is not surely continuous - /// and the greatest node ID can be actually less then \ref maxNodeId(). - /// - /// The ID of the \ref INVALID node is -1. - ///\return The ID of the node \c v. - static int id(Node v) { return v.n; } - /// Edge ID. - - /// The ID of a valid Edge is a nonnegative integer not greater than - /// \ref maxEdgeId(). The range of the ID's is not surely continuous - /// and the greatest edge ID can be actually less then \ref maxEdgeId(). - /// - /// The ID of the \ref INVALID edge is -1. - ///\return The ID of the edge \c e. - static int id(Edge e) { return e.n; } + static int id(Node v) { return v.id; } + static int id(Edge e) { return e.id; } /// Adds a new node to the graph. /// \warning It adds the new node to the front of the list. /// (i.e. the lastly added node becomes the first.) - Node addNode() { + Node addNode() { int n; - if(first_free_node==-1) - { - n = nodes.size(); - nodes.push_back(NodeT()); - } - else { + if(first_free_node==-1) { + n = nodes.size(); + nodes.push_back(NodeT()); + } else { n = first_free_node; first_free_node = nodes[n].next; } @@ -181,1319 +170,108 @@ nodes[n].first_in = nodes[n].first_out = -1; - Node nn; nn.n=n; - - //Update dynamic maps - node_maps.add(nn); - - return nn; + return Node(n); } Edge addEdge(Node u, Node v) { - int n; - - if(first_free_edge==-1) - { - n = edges.size(); - edges.push_back(EdgeT()); - } - else { + 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].tail = u.id; + edges[n].head = v.id; - 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].next_out = nodes[u.id].first_out; + if(nodes[u.id].first_out != -1) { + edges[nodes[u.id].first_out].prev_out = n; + } + + edges[n].next_in = nodes[v.id].first_in; + if(nodes[v.id].first_in != -1) { + edges[nodes[v.id].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; + nodes[u.id].first_out = nodes[v.id].first_in = n; - Edge e; e.n=n; - - //Update dynamic maps - edge_maps.add(e); - - return e; + return Edge(n); } - /// Finds an edge between two nodes. + void erase(const Node& node) { + int n = node.id; + + 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; - /// Finds an edge from node \c u to node \c v. - /// - /// If \c prev is \ref INVALID (this is the default value), then - /// It finds the first edge from \c u to \c v. Otherwise it looks for - /// the next edge from \c u to \c v after \c prev. - /// \return The found edge or INVALID if there is no such an edge. - Edge findEdge(Node u,Node v, Edge prev = INVALID) - { - int e = (prev.n==-1)? nodes[u.n].first_out : edges[prev.n].next_out; - while(e!=-1 && edges[e].tail!=v.n) e = edges[e].next_out; - prev.n=e; - return prev; } - private: - void eraseEdge(int n) { + void erase(const Edge& edge) { + int n = edge.id; - if(edges[n].next_in!=-1) + if(edges[n].next_in!=-1) { edges[edges[n].next_in].prev_in = edges[n].prev_in; - if(edges[n].prev_in!=-1) + } + + 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; + } else { + nodes[edges[n].head].first_in = edges[n].next_in; + } + - if(edges[n].next_out!=-1) + if(edges[n].next_out!=-1) { edges[edges[n].next_out].prev_out = edges[n].prev_out; - if(edges[n].prev_out!=-1) + } + + 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; + } else { + nodes[edges[n].tail].first_out = edges[n].next_out; + } edges[n].next_in = first_free_edge; first_free_edge = n; - //Update dynamic maps - Edge e; e.n=n; - edge_maps.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 - node_maps.erase(nn); - - } - - void erase(Edge e) { eraseEdge(e.n); } void clear() { - edge_maps.clear(); edges.clear(); - node_maps.clear(); nodes.clear(); - first_node=first_free_node=first_free_edge=-1; - } - - class Node { - friend class ListGraph; - template friend class NodeMap; - - friend class Edge; - friend class OutEdgeIt; - friend class InEdgeIt; - friend class SymEdge; - - protected: - int n; - friend int ListGraph::id(Node v); - Node(int nn) {n=nn;} - public: - Node() {} - Node (Invalid) { n=-1; } - bool operator==(const Node i) const {return n==i.n;} - bool operator!=(const Node i) const {return n!=i.n;} - bool operator<(const Node i) const {return nnodes[n].next; - return *this; - } - // ///Validity check - // operator bool() { return Node::operator bool(); } - }; - - class Edge { - friend class ListGraph; - template friend class EdgeMap; - - friend class SymListGraph; - - friend class Node; - friend class NodeIt; - protected: - int n; - friend int ListGraph::id(Edge e); - - public: - /// An Edge with id \c n. - - /// \bug It should be - /// obtained by a member function of the Graph. - Edge(int nn) {n=nn;} - - Edge() { } - Edge (Invalid) { n=-1; } - bool operator==(const Edge i) const {return n==i.n;} - bool operator!=(const Edge i) const {return n!=i.n;} - bool operator<(const Edge i) const {return nedges[n].next_in!=-1) n=G->edges[n].next_in; - else { - int nn; - for(nn=G->nodes[G->edges[n].head].next; - nn!=-1 && G->nodes[nn].first_in == -1; - nn = G->nodes[nn].next) ; - n = (nn==-1)?-1:G->nodes[nn].first_in; - } - return *this; - } - // ///Validity check - // operator bool() { return Edge::operator bool(); } - }; - - class OutEdgeIt : public Edge { - const ListGraph *G; - friend class ListGraph; - public: - OutEdgeIt() : Edge() { } - OutEdgeIt(const ListGraph& _G, Edge e) : Edge(e), G(&_G) { } - OutEdgeIt (Invalid i) : Edge(i) { } - - OutEdgeIt(const ListGraph& _G,const Node v) - : Edge(_G.nodes[v.n].first_out), G(&_G) {} - OutEdgeIt &operator++() { n=G->edges[n].next_out; return *this; } - // ///Validity check - // operator bool() { return Edge::operator bool(); } - }; - - class InEdgeIt : public Edge { - const ListGraph *G; - friend class ListGraph; - public: - InEdgeIt() : Edge() { } - InEdgeIt(const ListGraph& _G, Edge e) : Edge(e), G(&_G) { } - InEdgeIt (Invalid i) : Edge(i) { } - InEdgeIt(const ListGraph& _G,Node v) - : Edge(_G.nodes[v.n].first_in), G(&_G) { } - InEdgeIt &operator++() { n=G->edges[n].next_in; return *this; } - // ///Validity check - // operator bool() { return Edge::operator bool(); } - }; - }; - - ///Graph for bidirectional edges. - - ///The purpose of this graph structure is to handle graphs - ///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 lemon::SymListGraph::SymEdgeMap "SymEdgeMap" - ///that complements this - ///feature by - ///storing shared values for the edge pairs. The usual - ///\ref lemon::skeleton::StaticGraph::EdgeMap "EdgeMap" - ///can be used - ///as well. - /// - ///The oppositely directed edge can also be obtained easily - ///using \ref lemon::SymListGraph::opposite() "opposite()" member function. - /// - ///Here erase(Edge) deletes a pair of edges. - /// - ///\todo this date structure need some reconsiderations. Maybe it - ///should be implemented independently from ListGraph. - /* - class SymListGraph : public ListGraph - { - public: - - typedef SymListGraph Graph; - - // Create symmetric map registry. - CREATE_SYM_EDGE_MAP_REGISTRY; - // Create symmetric edge map. - CREATE_SYM_EDGE_MAP(ArrayMap); - - 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 = ListGraph::addEdge(u,v); - Edge f = ListGraph::addEdge(v,u); - sym_edge_maps.add(e); - sym_edge_maps.add(f); - - return e; - } - - void erase(Node n) { ListGraph::erase(n);} - ///The oppositely directed edge. - - ///Returns the oppositely directed - ///pair of the edge \c e. - static Edge opposite(Edge e) - { - Edge f; - f.n = e.n - 2*(e.n%2) + 1; - return f; - } - - ///Removes a pair of oppositely directed edges to the graph. - void erase(Edge e) { - Edge f = opposite(e); - sym_edge_maps.erase(e); - sym_edge_maps.erase(f); - ListGraph::erase(f); - ListGraph::erase(e); - } - };*/ - - class SymListGraph : public ListGraph { - typedef ListGraph Parent; - public: - - typedef SymListGraph Graph; - - typedef ListGraph::Node Node; - typedef ListGraph::NodeIt NodeIt; - - class SymEdge; - class SymEdgeIt; - - class Edge; - class EdgeIt; - class OutEdgeIt; - class InEdgeIt; - - template - class NodeMap : public Parent::NodeMap { - public: - NodeMap(const SymListGraph& g) - : SymListGraph::Parent::NodeMap(g) {} - NodeMap(const SymListGraph& g, Value v) - : SymListGraph::Parent::NodeMap(g, v) {} - template - NodeMap(const NodeMap& copy) - : SymListGraph::Parent::NodeMap(copy) { } - }; - - template - class SymEdgeMap : public Parent::EdgeMap { - public: - typedef SymEdge KeyType; - - SymEdgeMap(const SymListGraph& g) - : SymListGraph::Parent::EdgeMap(g) {} - SymEdgeMap(const SymListGraph& g, Value v) - : SymListGraph::Parent::EdgeMap(g, v) {} - template - SymEdgeMap(const SymEdgeMap& copy) - : SymListGraph::Parent::EdgeMap(copy) { } - - }; - - // Create edge map registry. - CREATE_EDGE_MAP_REGISTRY; - // Create edge maps. - CREATE_EDGE_MAP(ArrayMap); - - class Edge { - friend class SymListGraph; - friend class SymListGraph::EdgeIt; - friend class SymListGraph::OutEdgeIt; - friend class SymListGraph::InEdgeIt; - - protected: - int id; - - Edge(int pid) { id = pid; } - - public: - /// An Edge with id \c n. - - Edge() { } - Edge (Invalid) { id = -1; } - - operator SymEdge(){ return SymEdge(id >> 1);} - - bool operator==(const Edge i) const {return id == i.id;} - bool operator!=(const Edge i) const {return id != i.id;} - bool operator<(const Edge i) const {return id < i.id;} - // ///Validity check - // operator bool() { return n!=-1; } - }; - - class SymEdge : public ListGraph::Edge { - friend class SymListGraph; - friend class SymListGraph::Edge; - typedef ListGraph::Edge Parent; - - protected: - SymEdge(int pid) : Parent(pid) {} - public: - - SymEdge() { } - SymEdge(const ListGraph::Edge& i) : Parent(i) {} - SymEdge (Invalid) : Parent(INVALID) {} - - }; - - class OutEdgeIt { - Parent::OutEdgeIt out; - Parent::InEdgeIt in; - public: - OutEdgeIt() {} - OutEdgeIt(const SymListGraph& g, Edge e) { - if ((e.id & 1) == 0) { - out = Parent::OutEdgeIt(g, SymEdge(e)); - in = Parent::InEdgeIt(g, g.tail(e)); - } else { - out = Parent::OutEdgeIt(INVALID); - in = Parent::InEdgeIt(g, SymEdge(e)); - } - } - OutEdgeIt (Invalid i) : out(INVALID), in(INVALID) { } - - OutEdgeIt(const SymListGraph& g, const Node v) - : out(g, v), in(g, v) {} - OutEdgeIt &operator++() { - if (out != INVALID) { - ++out; - } else { - ++in; - } - return *this; - } - - operator Edge() const { - if (out == INVALID && in == INVALID) return INVALID; - return out != INVALID ? forward(out) : backward(in); - } - - bool operator==(const Edge i) const {return Edge(*this) == i;} - bool operator!=(const Edge i) const {return Edge(*this) != i;} - bool operator<(const Edge i) const {return Edge(*this) < i;} - }; - - class InEdgeIt { - Parent::OutEdgeIt out; - Parent::InEdgeIt in; - public: - InEdgeIt() {} - InEdgeIt(const SymListGraph& g, Edge e) { - if ((e.id & 1) == 0) { - out = Parent::OutEdgeIt(g, SymEdge(e)); - in = Parent::InEdgeIt(g, g.tail(e)); - } else { - out = Parent::OutEdgeIt(INVALID); - in = Parent::InEdgeIt(g, SymEdge(e)); - } - } - InEdgeIt (Invalid i) : out(INVALID), in(INVALID) { } - - InEdgeIt(const SymListGraph& g, const Node v) - : out(g, v), in(g, v) {} - - InEdgeIt &operator++() { - if (out != INVALID) { - ++out; - } else { - ++in; - } - return *this; - } - - operator Edge() const { - if (out == INVALID && in == INVALID) return INVALID; - return out != INVALID ? backward(out) : forward(in); - } - - bool operator==(const Edge i) const {return Edge(*this) == i;} - bool operator!=(const Edge i) const {return Edge(*this) != i;} - bool operator<(const Edge i) const {return Edge(*this) < i;} - }; - - class SymEdgeIt : public Parent::EdgeIt { - - public: - SymEdgeIt() {} - - SymEdgeIt(const SymListGraph& g) - : SymListGraph::Parent::EdgeIt(g) {} - - SymEdgeIt(const SymListGraph& g, SymEdge e) - : SymListGraph::Parent::EdgeIt(g, e) {} - - SymEdgeIt(Invalid i) - : SymListGraph::Parent::EdgeIt(INVALID) {} - - SymEdgeIt& operator++() { - SymListGraph::Parent::EdgeIt::operator++(); - return *this; - } - - operator SymEdge() const { - return SymEdge - (static_cast(*this)); - } - bool operator==(const SymEdge i) const {return SymEdge(*this) == i;} - bool operator!=(const SymEdge i) const {return SymEdge(*this) != i;} - bool operator<(const SymEdge i) const {return SymEdge(*this) < i;} - }; - - class EdgeIt { - SymEdgeIt it; - bool fw; - public: - EdgeIt(const SymListGraph& g) : it(g), fw(true) {} - EdgeIt (Invalid i) : it(i) { } - EdgeIt(const SymListGraph& g, Edge e) - : it(g, SymEdge(e)), fw(id(e) & 1 == 0) { } - EdgeIt() { } - EdgeIt& operator++() { - fw = !fw; - if (fw) ++it; - return *this; - } - operator Edge() const { - if (it == INVALID) return INVALID; - return fw ? forward(it) : backward(it); - } - bool operator==(const Edge i) const {return Edge(*this) == i;} - bool operator!=(const Edge i) const {return Edge(*this) != i;} - bool operator<(const Edge i) const {return Edge(*this) < i;} - - }; - - ///Number of nodes. - int nodeNum() const { return Parent::nodeNum(); } - ///Number of edges. - int edgeNum() const { return 2*Parent::edgeNum(); } - ///Number of symmetric edges. - int symEdgeNum() const { return Parent::edgeNum(); } - - ///Set the expected maximum number of edges. - - ///With this function, it is possible to set the expected number of edges. - ///The use of this fasten the building of the graph and makes - ///it possible to avoid the superfluous memory allocation. - void reserveSymEdge(int n) { Parent::reserveEdge(n); }; - - /// Maximum node ID. - - /// Maximum node ID. - ///\sa id(Node) - int maxNodeId() const { return Parent::maxNodeId(); } - /// Maximum edge ID. - - /// Maximum edge ID. - ///\sa id(Edge) - int maxEdgeId() const { return 2*Parent::maxEdgeId(); } - /// Maximum symmetric edge ID. - - /// Maximum symmetric edge ID. - ///\sa id(SymEdge) - int maxSymEdgeId() const { return Parent::maxEdgeId(); } - - - Node tail(Edge e) const { - return (e.id & 1) == 0 ? - Parent::tail(SymEdge(e)) : Parent::head(SymEdge(e)); - } - - Node head(Edge e) const { - return (e.id & 1) == 0 ? - Parent::head(SymEdge(e)) : Parent::tail(SymEdge(e)); - } - - Node tail(SymEdge e) const { - return Parent::tail(e); - } - - Node head(SymEdge e) const { - return Parent::head(e); - } - - NodeIt& first(NodeIt& v) const { - v=NodeIt(*this); return v; } - EdgeIt& first(EdgeIt& e) const { - e=EdgeIt(*this); return e; } - SymEdgeIt& first(SymEdgeIt& e) const { - e=SymEdgeIt(*this); return e; } - OutEdgeIt& first(OutEdgeIt& e, const Node v) const { - e=OutEdgeIt(*this,v); return e; } - InEdgeIt& first(InEdgeIt& e, const Node v) const { - e=InEdgeIt(*this,v); return e; } - - /// Node ID. - - /// The ID of a valid Node is a nonnegative integer not greater than - /// \ref maxNodeId(). The range of the ID's is not surely continuous - /// and the greatest node ID can be actually less then \ref maxNodeId(). - /// - /// The ID of the \ref INVALID node is -1. - ///\return The ID of the node \c v. - static int id(Node v) { return Parent::id(v); } - /// Edge ID. - - /// The ID of a valid Edge is a nonnegative integer not greater than - /// \ref maxEdgeId(). The range of the ID's is not surely continuous - /// and the greatest edge ID can be actually less then \ref maxEdgeId(). - /// - /// The ID of the \ref INVALID edge is -1. - ///\return The ID of the edge \c e. - static int id(Edge e) { return e.id; } - - /// The ID of a valid SymEdge is a nonnegative integer not greater than - /// \ref maxSymEdgeId(). The range of the ID's is not surely continuous - /// and the greatest edge ID can be actually less then \ref maxSymEdgeId(). - /// - /// The ID of the \ref INVALID symmetric edge is -1. - ///\return The ID of the edge \c e. - static int id(SymEdge e) { return Parent::id(e); } - - /// Adds a new node to the graph. - - /// \warning It adds the new node to the front of the list. - /// (i.e. the lastly added node becomes the first.) - Node addNode() { - return Parent::addNode(); - } - - SymEdge addEdge(Node u, Node v) { - SymEdge se = Parent::addEdge(u, v); - edge_maps.add(forward(se)); - edge_maps.add(backward(se)); - return se; - } - - /// Finds an edge between two nodes. - - /// Finds an edge from node \c u to node \c v. - /// - /// If \c prev is \ref INVALID (this is the default value), then - /// It finds the first edge from \c u to \c v. Otherwise it looks for - /// the next edge from \c u to \c v after \c prev. - /// \return The found edge or INVALID if there is no such an edge. - Edge findEdge(Node u, Node v, Edge prev = INVALID) - { - if (prev == INVALID || id(prev) & 1 == 0) { - SymEdge se = Parent::findEdge(u, v, SymEdge(prev)); - if (se != INVALID) return forward(se); - } else { - SymEdge se = Parent::findEdge(v, u, SymEdge(prev)); - if (se != INVALID) return backward(se); - } - return INVALID; - } - -// /// Finds an symmetric edge between two nodes. - -// /// Finds an symmetric edge from node \c u to node \c v. -// /// -// /// If \c prev is \ref INVALID (this is the default value), then -// /// It finds the first edge from \c u to \c v. Otherwise it looks for -// /// the next edge from \c u to \c v after \c prev. -// /// \return The found edge or INVALID if there is no such an edge. - -// SymEdge findEdge(Node u, Node v, SymEdge prev = INVALID) -// { -// if (prev == INVALID || id(prev) & 1 == 0) { -// SymEdge se = Parent::findEdge(u, v, SymEdge(prev)); -// if (se != INVALID) return se; -// } else { -// SymEdge se = Parent::findEdge(v, u, SymEdge(prev)); -// if (se != INVALID) return se; -// } -// return INVALID; -// } - - public: - - void erase(Node n) { - for (OutEdgeIt it(*this, n); it != INVALID; ++it) { - edge_maps.erase(it); - edge_maps.erase(opposite(it)); - } - Parent::erase(n); - } - - void erase(SymEdge e) { - edge_maps.erase(forward(e)); - edge_maps.erase(backward(e)); - Parent::erase(e); - }; - - void clear() { - edge_maps.clear(); - Parent::clear(); - } - - static Edge opposite(Edge e) { - return Edge(id(e) ^ 1); - } - - static Edge forward(SymEdge e) { - return Edge(id(e) << 1); - } - - static Edge backward(SymEdge e) { - return Edge((id(e) << 1) | 1); + first_node = first_free_node = first_free_edge = -1; } }; - ///A graph class containing only nodes. + typedef AlterableGraphExtender AlterableListGraphBase; + typedef IterableGraphExtender IterableListGraphBase; + typedef IdMappableGraphExtender IdMappableListGraphBase; + typedef DefaultMappableGraphExtender MappableListGraphBase; + typedef ExtendableGraphExtender ExtendableListGraphBase; + typedef ClearableGraphExtender ClearableListGraphBase; + typedef ErasableGraphExtender ErasableListGraphBase; - ///This class implements a graph structure without edges. - ///The most useful application of this class is to be the node set of an - ///\ref EdgeSet class. - /// - ///It conforms to - ///the \ref skeleton::ExtendableGraph "ExtendableGraph" concept - ///with the exception that you cannot - ///add (or delete) edges. The usual edge iterators are exists, but they are - ///always \ref INVALID. - ///\sa skeleton::ExtendableGraph - ///\sa EdgeSet - class NodeSet { + typedef ErasableListGraphBase ListGraph; - //Nodes are double linked. - //The free nodes are only single linked using the "next" field. - struct NodeT - { - int first_in,first_out; - int prev, next; - // NodeT() {} - }; +} - std::vector nodes; - //The first node - int first_node; - //The first free node - int first_free_node; - - public: - typedef NodeSet Graph; - - class Node; - class Edge; + - public: - - class NodeIt; - class EdgeIt; - class OutEdgeIt; - class InEdgeIt; - - // Create node map registry. - CREATE_NODE_MAP_REGISTRY; - // Create node maps. - CREATE_NODE_MAP(ArrayMap); - - /// Creating empty map structure for edges. - template - class EdgeMap { - public: - EdgeMap(const Graph&) {} - EdgeMap(const Graph&, const Value&) {} - - EdgeMap(const EdgeMap&) {} - template EdgeMap(const CMap&) {} - - EdgeMap& operator=(const EdgeMap&) {} - template EdgeMap& operator=(const CMap&) {} - - class ConstIterator { - public: - bool operator==(const ConstIterator&) {return true;} - bool operator!=(const ConstIterator&) {return false;} - }; - - typedef ConstIterator Iterator; - - Iterator begin() { return Iterator();} - Iterator end() { return Iterator();} - - ConstIterator begin() const { return ConstIterator();} - ConstIterator end() const { return ConstIterator();} - - }; - - public: - - ///Default constructor - NodeSet() - : nodes(), first_node(-1), first_free_node(-1) {} - ///Copy constructor - NodeSet(const NodeSet &_g) - : nodes(_g.nodes), first_node(_g.first_node), - first_free_node(_g.first_free_node) {} - - ///Number of nodes. - int nodeNum() const { return nodes.size(); } - ///Number of edges. - int edgeNum() const { return 0; } - - /// Maximum node ID. - - /// Maximum node ID. - ///\sa id(Node) - int maxNodeId() const { return nodes.size()-1; } - /// Maximum edge ID. - - /// Maximum edge ID. - ///\sa id(Edge) - int maxEdgeId() const { return 0; } - - Node tail(Edge e) const { return INVALID; } - Node head(Edge e) const { return INVALID; } - - NodeIt& first(NodeIt& v) const { - v=NodeIt(*this); return v; } - EdgeIt& first(EdgeIt& e) const { - e=EdgeIt(*this); return e; } - OutEdgeIt& first(OutEdgeIt& e, const Node v) const { - e=OutEdgeIt(*this,v); return e; } - InEdgeIt& first(InEdgeIt& e, const Node v) const { - e=InEdgeIt(*this,v); return e; } - - /// Node ID. - - /// The ID of a valid Node is a nonnegative integer not greater than - /// \ref maxNodeId(). The range of the ID's is not surely continuous - /// and the greatest node ID can be actually less then \ref maxNodeId(). - /// - /// The ID of the \ref INVALID node is -1. - ///\return The ID of the node \c v. - static int id(Node v) { return v.n; } - /// Edge ID. - - /// The ID of a valid Edge is a nonnegative integer not greater than - /// \ref maxEdgeId(). The range of the ID's is not surely continuous - /// and the greatest edge ID can be actually less then \ref maxEdgeId(). - /// - /// The ID of the \ref INVALID edge is -1. - ///\return The ID of the edge \c e. - static int id(Edge e) { return -1; } - - /// Adds a new node to the graph. - - /// \warning It adds the new node to the front of the list. - /// (i.e. the lastly added node becomes the first.) - Node addNode() { - 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 - node_maps.add(nn); - - return nn; - } - - void erase(Node nn) { - int n=nn.n; - - 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 - node_maps.erase(nn); - } - - - Edge findEdge(Node u,Node v, Edge prev = INVALID) - { - return INVALID; - } - - void clear() { - node_maps.clear(); - nodes.clear(); - first_node = first_free_node = -1; - } - - class Node { - friend class NodeSet; - template friend class NodeMap; - - friend class Edge; - friend class OutEdgeIt; - friend class InEdgeIt; - - protected: - int n; - friend int NodeSet::id(Node v); - Node(int nn) {n=nn;} - public: - Node() {} - Node (Invalid i) { n=-1; } - bool operator==(const Node i) const {return n==i.n;} - bool operator!=(const Node i) const {return n!=i.n;} - bool operator<(const Node i) const {return nnodes[n].next; - return *this; - } - }; - - class Edge { - public: - Edge() { } - Edge (Invalid) { } - bool operator==(const Edge i) const {return true;} - bool operator!=(const Edge i) const {return false;} - bool operator<(const Edge i) const {return false;} - }; - - class EdgeIt : public Edge { - public: - EdgeIt(const NodeSet& G) : Edge() { } - EdgeIt(const NodeSet&, Edge) : Edge() { } - EdgeIt (Invalid i) : Edge(i) { } - EdgeIt() : Edge() { } - EdgeIt operator++() { return INVALID; } - }; - - class OutEdgeIt : public Edge { - friend class NodeSet; - public: - OutEdgeIt() : Edge() { } - OutEdgeIt(const NodeSet&, Edge) : Edge() { } - OutEdgeIt (Invalid i) : Edge(i) { } - OutEdgeIt(const NodeSet& G,const Node v) : Edge() {} - OutEdgeIt operator++() { return INVALID; } - }; - - class InEdgeIt : public Edge { - friend class NodeSet; - public: - InEdgeIt() : Edge() { } - InEdgeIt(const NodeSet&, Edge) : Edge() { } - InEdgeIt (Invalid i) : Edge(i) { } - InEdgeIt(const NodeSet& G,Node v) :Edge() {} - InEdgeIt operator++() { return INVALID; } - }; - - }; - - - - ///Graph structure using a node set of another graph. - - ///This structure can be used to establish another graph over a node set - /// of an existing one. The node iterator will go through the nodes of the - /// original graph, and the NodeMap's of both graphs will convert to - /// each other. - /// - ///\warning Adding or deleting nodes from the graph is not safe if an - ///\ref EdgeSet is currently attached to it! - /// - ///\todo Make it possible to add/delete edges from the base graph - ///(and from \ref EdgeSet, as well) - /// - ///\param GG The type of the graph which shares its node set with this class. - ///Its interface must conform to the - ///\ref skeleton::StaticGraph "StaticGraph" concept. - /// - ///It conforms to the - ///\ref skeleton::ExtendableGraph "ExtendableGraph" concept. - ///\sa skeleton::ExtendableGraph. - ///\sa NodeSet. - template - class EdgeSet { - - typedef GG NodeGraphType; - - NodeGraphType &G; - - public: - - class Node; - class Edge; - class OutEdgeIt; - class InEdgeIt; - class SymEdge; - - typedef EdgeSet Graph; - - int id(Node v) const; - - class Node : public NodeGraphType::Node { - friend class EdgeSet; - - friend class Edge; - friend class OutEdgeIt; - friend class InEdgeIt; - friend class SymEdge; - - public: - friend int EdgeSet::id(Node v) const; - public: - Node() : NodeGraphType::Node() {} - Node (Invalid i) : NodeGraphType::Node(i) {} - Node(const typename NodeGraphType::Node &n) : NodeGraphType::Node(n) {} - }; - - class NodeIt : public NodeGraphType::NodeIt { - friend class EdgeSet; - public: - NodeIt() : NodeGraphType::NodeIt() { } - NodeIt(const EdgeSet& _G,Node n) : NodeGraphType::NodeIt(_G.G,n) { } - NodeIt (Invalid i) : NodeGraphType::NodeIt(i) {} - NodeIt(const EdgeSet& _G) : NodeGraphType::NodeIt(_G.G) { } - NodeIt(const typename NodeGraphType::NodeIt &n) - : NodeGraphType::NodeIt(n) {} - - operator Node() { return Node(*this);} - NodeIt &operator++() - { this->NodeGraphType::NodeIt::operator++(); return *this;} - }; - - private: - //Edges are double linked. - //The free edges are only single linked using the "next_in" field. - struct NodeT - { - int first_in,first_out; - NodeT() : first_in(-1), first_out(-1) { } - }; - - struct EdgeT - { - Node head, tail; - int prev_in, prev_out; - int next_in, next_out; - }; - - - typename NodeGraphType::template NodeMap nodes; - - std::vector edges; - //The first free edge - int first_free_edge; - - public: - - class Node; - class Edge; - - class NodeIt; - class EdgeIt; - class OutEdgeIt; - class InEdgeIt; - - - // Create edge map registry. - CREATE_EDGE_MAP_REGISTRY; - // Create edge maps. - CREATE_EDGE_MAP(ArrayMap); - - // Import node maps from the NodeGraphType. - IMPORT_NODE_MAP(NodeGraphType, graph.G, EdgeSet, graph); - - - public: - - ///Constructor - - ///Construates a new graph based on the nodeset of an existing one. - ///\param _G the base graph. - explicit EdgeSet(NodeGraphType &_G) - : G(_G), nodes(_G), edges(), - first_free_edge(-1) {} - ///Copy constructor - - ///Makes a copy of an EdgeSet. - ///It will be based on the same graph. - explicit EdgeSet(const EdgeSet &_g) - : G(_g.G), nodes(_g.G), edges(_g.edges), - first_free_edge(_g.first_free_edge) {} - - ///Number of nodes. - int nodeNum() const { return G.nodeNum(); } - ///Number of edges. - int edgeNum() const { return edges.size(); } - - /// Maximum node ID. - - /// Maximum node ID. - ///\sa id(Node) - int maxNodeId() const { return G.maxNodeId(); } - /// Maximum edge ID. - - /// Maximum edge ID. - ///\sa id(Edge) - int maxEdgeId() const { return edges.size()-1; } - - Node tail(Edge e) const { return edges[e.n].tail; } - Node head(Edge e) const { return edges[e.n].head; } - - NodeIt& first(NodeIt& v) const { - v=NodeIt(*this); return v; } - EdgeIt& first(EdgeIt& e) const { - e=EdgeIt(*this); return e; } - OutEdgeIt& first(OutEdgeIt& e, const Node v) const { - e=OutEdgeIt(*this,v); return e; } - InEdgeIt& first(InEdgeIt& e, const Node v) const { - e=InEdgeIt(*this,v); return e; } - - /// Node ID. - - /// The ID of a valid Node is a nonnegative integer not greater than - /// \ref maxNodeId(). The range of the ID's is not surely continuous - /// and the greatest node ID can be actually less then \ref maxNodeId(). - /// - /// The ID of the \ref INVALID node is -1. - ///\return The ID of the node \c v. - int id(Node v) { return G.id(v); } - /// Edge ID. - - /// The ID of a valid Edge is a nonnegative integer not greater than - /// \ref maxEdgeId(). The range of the ID's is not surely continuous - /// and the greatest edge ID can be actually less then \ref maxEdgeId(). - /// - /// The ID of the \ref INVALID edge is -1. - ///\return The ID of the edge \c e. - static int id(Edge e) { return e.n; } - - /// Adds a new node to the graph. - Node addNode() { return G.addNode(); } - - Edge addEdge(Node u, Node v) { - 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; edges[n].head = v; - - edges[n].next_out = nodes[u].first_out; - if(nodes[u].first_out != -1) edges[nodes[u].first_out].prev_out = n; - edges[n].next_in = nodes[v].first_in; - if(nodes[v].first_in != -1) edges[nodes[v].first_in].prev_in = n; - edges[n].prev_in = edges[n].prev_out = -1; - - nodes[u].first_out = nodes[v].first_in = n; - - Edge e; e.n=n; - - //Update dynamic maps - edge_maps.add(e); - - return e; - } - - /// Finds an edge between two nodes. - - /// Finds an edge from node \c u to node \c v. - /// - /// If \c prev is \ref INVALID (this is the default value), then - /// It finds the first edge from \c u to \c v. Otherwise it looks for - /// the next edge from \c u to \c v after \c prev. - /// \return The found edge or INVALID if there is no such an edge. - Edge findEdge(Node u,Node v, Edge prev = INVALID) - { - int e = (prev.n==-1)? nodes[u].first_out : edges[prev.n].next_out; - while(e!=-1 && edges[e].tail!=v) e = edges[e].next_out; - prev.n=e; - return prev; - } - - 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; - edge_maps.erase(e); - } - - public: - - void erase(Edge e) { eraseEdge(e.n); } - - ///Clear all edges. (Doesn't clear the nodes!) - void clear() { - edge_maps.clear(); - edges.clear(); - first_free_edge=-1; - } - - - class Edge { - public: - friend class EdgeSet; - template friend class EdgeMap; - - friend class Node; - friend class NodeIt; - protected: - int n; - friend int EdgeSet::id(Edge e) const; - - Edge(int nn) {n=nn;} - public: - Edge() { } - Edge (Invalid) { n=-1; } - bool operator==(const Edge i) const {return n==i.n;} - bool operator!=(const Edge i) const {return n!=i.n;} - bool operator<(const Edge i) const {return n friend class EdgeMap; - - const EdgeSet *G; - public: - EdgeIt(const EdgeSet& _G) : Edge(), G(&_G) { - NodeIt m; - for(G->first(m); - m!=INVALID && G->nodes[m].first_in == -1; ++m); - ///\bug AJJAJ! This is a non sense!!!!!!! - this->n = m!=INVALID?-1:G->nodes[m].first_in; - } - EdgeIt(const EdgeSet& _G, Edge e) : Edge(e), G(&_G) { } - EdgeIt (Invalid i) : Edge(i) { } - EdgeIt() : Edge() { } - ///. - - ///\bug UNIMPLEMENTED!!!!! - // - EdgeIt &operator++() { - return *this; - } - }; - - class OutEdgeIt : public Edge { - const EdgeSet *G; - friend class EdgeSet; - public: - OutEdgeIt() : Edge() { } - OutEdgeIt (Invalid i) : Edge(i) { } - OutEdgeIt(const EdgeSet& _G, Edge e) : Edge(e), G(&_G) { } - - OutEdgeIt(const EdgeSet& _G,const Node v) : - Edge(_G.nodes[v].first_out), G(&_G) { } - OutEdgeIt &operator++() { - Edge::n = G->edges[Edge::n].next_out; - return *this; - } - }; - - class InEdgeIt : public Edge { - const EdgeSet *G; - friend class EdgeSet; - public: - InEdgeIt() : Edge() { } - InEdgeIt (Invalid i) : Edge(i) { } - InEdgeIt(const EdgeSet& _G, Edge e) : Edge(e), G(&_G) { } - InEdgeIt(const EdgeSet& _G,Node v) - : Edge(_G.nodes[v].first_in), G(&_G) { } - InEdgeIt &operator++() { - Edge::n = G->edges[Edge::n].next_in; - return *this; - } - }; - - }; - - template - inline int EdgeSet::id(Node v) const { return G.id(v); } - -/// @} - -} //namespace lemon - -#endif //LEMON_LIST_GRAPH_H +#endif