# HG changeset patch # User deba # Date 1089358392 0 # Node ID 625de6f1e7662591934cc58503ca98d5ba3201a5 # Parent 89d97db9c92795842e48401b8ecf83fbeb91bfeb diff -r 89d97db9c927 -r 625de6f1e766 src/work/deba/bin_heap.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/work/deba/bin_heap.h Fri Jul 09 07:33:12 2004 +0000 @@ -0,0 +1,246 @@ +// -*- C++ -*- // + +/* FIXME: Copyright ... + * + * This implementation is heavily based on STL's heap functions and + * the similar class by Alpar Juttner in IKTA... + */ + +/****** + * + * BinHeap + * + * Ez az osztaly item-prioritas parok tarolasara alkalmas binaris kupacot + * valosit meg. + * A kupacban legfolul mindig az a par talalhato, amiben a prioritas a + * legkisebb. (Gondolj a Dijkstra pont-tavolsag kupacara; igazabol ahhoz + * lett keszitve...) + * + * Megjegyzes: a kupacos temakorokben a prioritast kulcsnak szoktak nevezni, + * de mivel ez zavaro tud lenni a property-map-es kulcs-ertek szohasznalata + * miatt, megprobaltunk valami semleges elnevezeseket kitalalni. + * + * A hasznalatahoz szukseg van egy irhato/olvashato property_map-re, ami + * az itemekhez egy int-et tud tarolni (ezzel tudom megkeresni az illeto + * elemet a kupacban a csokkentes es hasonlo muveletekhez). + * A map-re csak referenciat tarol, ugy hogy a kupac elete folyan a map-nek + * is elnie kell. (???) + * + * Ketfele modon hasznalhato: + * Lusta mod: + * set(Item, Prio) metodussal pakolunk a kupacba, + * aztan o majd eldonti, hogy ez az elem mar benne van-e es ha igen, akkor + * csokkentettunk-e rajta, vagy noveltunk. + * Ehhez nagyon fontos, hogy az atadott property map inicializalva legyen + * minden szobajovo kulcs ertekre, -1 -es ertekkel! + * Es ilyen esetben a kulcsokrol lekerdezheto az allapotuk a state metodussal: + * (nem jart meg a kupacban PRE_HEAP=-1, epp a kupacban van IN_HEAP=0, + * mar kikerult a kupacbol POST_HEAP=-2). + * Szoval ebben a modban a kupac nagyjabol hasznalhato property_map-kent, csak + * meg meg tudja mondani a "legkisebb" prioritasu elemet. De csak nagyjabol, + * hiszen a kupacbol kikerult elemeknek elvesz az ertekuk... + * + * Kozvetlen mod: + * push(Item, Prio) metodussal belerakunk a kupacba (ha az illeto kulcs mar + * benn volt, akkor gaz). + * increase/decrease(Item i, Prio new_prio) metodusokkal lehet + * novelni/csokkenteni az illeto elemhez tartozo prioritast. (Ha nem volt + * megbenne a kupacban az illeto elem, vagy nem abba az iranyba valtoztattad + * az erteket, amerre mondtad -- gaz). + * + * Termeszetesen a fenti ket modot ertelemszeruen lehet keverni. + * Ja es mindig nagyon gaz, ha belepiszkalsz a map-be, amit a kupac + * hasznal. :-)) + * + * + * Bocs, most faradt vagyok, majd egyszer leforditom. (Misi) + * + */ + + +#ifndef HUGO_BIN_HEAP_H +#define HUGO_BIN_HEAP_H + +///\ingroup auxdat +///\file +///\brief Binary Heap implementation. + +#include +#include +#include + +namespace hugo { + + /// \addtogroup auxdat + /// @{ + + /// A Binary Heap implementation. + template > + class BinHeap { + + public: + typedef Item ItemType; + // FIXME: stl-ben nem ezt hivjak value_type -nak, hanem a kovetkezot... + typedef Prio PrioType; + typedef std::pair PairType; + typedef ItemIntMap ItemIntMapType; + typedef Compare PrioCompare; + + /** + * Each Item element have a state associated to it. It may be "in heap", + * "pre heap" or "post heap". The later two are indifferent from the + * heap's point of view, but may be useful to the user. + * + * The ItemIntMap _should_ be initialized in such way, that it maps + * PRE_HEAP (-1) to any element to be put in the heap... + */ + ///\todo it is used nowhere + /// + enum state_enum { + IN_HEAP = 0, + PRE_HEAP = -1, + POST_HEAP = -2 + }; + + private: + std::vector data; + Compare comp; + // FIXME: jo ez igy??? + ItemIntMap &iim; + + public: + BinHeap(ItemIntMap &_iim) : iim(_iim) {} + BinHeap(ItemIntMap &_iim, const Compare &_comp) : comp(_comp), iim(_iim) {} + + + int size() const { return data.size(); } + bool empty() const { return data.empty(); } + + private: + static int parent(int i) { return (i-1)/2; } + static int second_child(int i) { return 2*i+2; } + bool less(const PairType &p1, const PairType &p2) const { + return comp(p1.second, p2.second); + } + + int bubble_up(int hole, PairType p); + int bubble_down(int hole, PairType p, int length); + + void move(const PairType &p, int i) { + data[i] = p; + iim.set(p.first, i); + } + + void rmidx(int h) { + int n = data.size()-1; + if( h>=0 && h<=n ) { + iim.set(data[h].first, POST_HEAP); + if ( h=0 ) + s=0; + return state_enum(s); + } + + }; // class BinHeap + + + template + int BinHeap::bubble_up(int hole, PairType p) { + int par = parent(hole); + while( hole>0 && less(p,data[par]) ) { + move(data[par],hole); + hole = par; + par = parent(hole); + } + move(p, hole); + return hole; + } + + template + int BinHeap::bubble_down(int hole, PairType p, int length) { + int child = second_child(hole); + while(child < length) { + if( less(data[child-1], data[child]) ) { + --child; + } + if( !less(data[child], p) ) + goto ok; + move(data[child], hole); + hole = child; + child = second_child(hole); + } + child--; + if( child +#include + +namespace hugo { + +/// \addtogroup galgs +/// @{ + + ///%Dijkstra algorithm class. + + ///This class provides an efficient implementation of %Dijkstra algorithm. + ///The edge lengths are passed to the algorithm using a + ///\ref ReadMapSkeleton "readable map", + ///so it is easy to change it to any kind of length. + /// + ///The type of the length is determined by the \c ValueType of the length map. + /// + ///It is also possible to change the underlying priority heap. + /// + ///\param GR The graph type the algorithm runs on. + ///\param LM This read-only + ///EdgeMap + ///determines the + ///lengths of the edges. It is read once for each edge, so the map + ///may involve in relatively time consuming process to compute the edge + ///length if it is necessary. The default map type is + ///\ref GraphSkeleton::EdgeMap "Graph::EdgeMap" + ///\param Heap The heap type used by the %Dijkstra + ///algorithm. The default + ///is using \ref BinHeap "binary heap". + /// + ///\author Jacint Szabo and Alpar Juttner + ///\todo We need a typedef-names should be standardized. (-: + +#ifdef DOXYGEN + template +#else + template , + template class Heap = BinHeap > +#endif + class Dijkstra{ + public: + ///The type of the underlying graph. + typedef GR Graph; + typedef typename Graph::Node Node; + typedef typename Graph::NodeIt NodeIt; + typedef typename Graph::Edge Edge; + typedef typename Graph::OutEdgeIt OutEdgeIt; + + ///The type of the length of the edges. + typedef typename LM::ValueType ValueType; + ///The type of the map that stores the edge lengths. + typedef LM LengthMap; + ///\brief The type of the map that stores the last + ///edges of the shortest paths. + typedef typename Graph::template NodeMap PredMap; + ///\brief The type of the map that stores the last but one + ///nodes of the shortest paths. + typedef typename Graph::template NodeMap PredNodeMap; + ///The type of the map that stores the dists of the nodes. + typedef typename Graph::template NodeMap DistMap; + + private: + const Graph *G; + const LM *length; + // bool local_length; + PredMap *predecessor; + bool local_predecessor; + PredNodeMap *pred_node; + bool local_pred_node; + DistMap *distance; + bool local_distance; + + ///Initialize maps + + ///\todo Error if \c G or are \c NULL. What about \c length? + ///\todo Better memory allocation (instead of new). + void init_maps() + { +// if(!length) { +// local_length = true; +// length = new LM(G); +// } + if(!predecessor) { + local_predecessor = true; + predecessor = new PredMap(*G); + } + if(!pred_node) { + local_pred_node = true; + pred_node = new PredNodeMap(*G); + } + if(!distance) { + local_distance = true; + distance = new DistMap(*G); + } + } + + public : + + Dijkstra(const Graph& _G, const LM& _length) : + G(&_G), length(&_length), + predecessor(NULL), pred_node(NULL), distance(NULL), + local_predecessor(false), local_pred_node(false), local_distance(false) + { } + + ~Dijkstra() + { + // if(local_length) delete length; + if(local_predecessor) delete predecessor; + if(local_pred_node) delete pred_node; + if(local_distance) delete distance; + } + + ///Sets the graph the algorithm will run on. + + ///Sets the graph the algorithm will run on. + ///\return (*this) + Dijkstra &setGraph(const Graph &_G) + { + G = &_G; + return *this; + } + ///Sets the length map. + + ///Sets the length map. + ///\return (*this) + Dijkstra &setLengthMap(const LM &m) + { +// if(local_length) { +// delete length; +// local_length=false; +// } + length = &m; + return *this; + } + + ///Sets the map storing the predecessor edges. + + ///Sets the map storing the predecessor edges. + ///If you don't use this function before calling \ref run(), + ///it will allocate one. The destuctor deallocates this + ///automatically allocated map, of course. + ///\return (*this) + Dijkstra &setPredMap(PredMap &m) + { + if(local_predecessor) { + delete predecessor; + local_predecessor=false; + } + predecessor = &m; + return *this; + } + + ///Sets the map storing the predecessor nodes. + + ///Sets the map storing the predecessor nodes. + ///If you don't use this function before calling \ref run(), + ///it will allocate one. The destuctor deallocates this + ///automatically allocated map, of course. + ///\return (*this) + Dijkstra &setPredNodeMap(PredNodeMap &m) + { + if(local_pred_node) { + delete pred_node; + local_pred_node=false; + } + pred_node = &m; + return *this; + } + + ///Sets the map storing the distances calculated by the algorithm. + + ///Sets the map storing the distances calculated by the algorithm. + ///If you don't use this function before calling \ref run(), + ///it will allocate one. The destuctor deallocates this + ///automatically allocated map, of course. + ///\return (*this) + Dijkstra &setDistMap(DistMap &m) + { + if(local_distance) { + delete distance; + local_distance=false; + } + distance = &m; + return *this; + } + + ///Runs %Dijkstra algorithm from node \c s. + + ///This method runs the %Dijkstra algorithm from a root node \c s + ///in order to + ///compute the + ///shortest path to each node. The algorithm computes + ///- The shortest path tree. + ///- The distance of each node from the root. + + void run(Node s) { + + init_maps(); + + for ( NodeIt u(*G) ; G->valid(u) ; G->next(u) ) { + predecessor->set(u,INVALID); + pred_node->set(u,INVALID); + } + + typename GR::template NodeMap heap_map(*G,-1); + + typedef Heap, + std::less > + HeapType; + + HeapType heap(heap_map); + + heap.push(s,0); + + while ( !heap.empty() ) { + + Node v=heap.top(); + ValueType oldvalue=heap[v]; + heap.pop(); + distance->set(v, oldvalue); + + + for(OutEdgeIt e(*G,v); G->valid(e); G->next(e)) { + Node w=G->bNode(e); + + switch(heap.state(w)) { + case HeapType::PRE_HEAP: + heap.push(w,oldvalue+(*length)[e]); + predecessor->set(w,e); + pred_node->set(w,v); + break; + case HeapType::IN_HEAP: + if ( oldvalue+(*length)[e] < heap[w] ) { + heap.decrease(w, oldvalue+(*length)[e]); + predecessor->set(w,e); + pred_node->set(w,v); + } + break; + case HeapType::POST_HEAP: + break; + } + } + } + } + + ///The distance of a node from the root. + + ///Returns the distance of a node from the root. + ///\pre \ref run() must be called before using this function. + ///\warning If node \c v in unreachable from the root the return value + ///of this funcion is undefined. + ValueType dist(Node v) const { return (*distance)[v]; } + + ///Returns the 'previous edge' of the shortest path tree. + + ///For a node \c v it returns the 'previous edge' of the shortest path tree, + ///i.e. it returns the last edge from a shortest path from the root to \c + ///v. It is \ref INVALID + ///if \c v is unreachable from the root or if \c v=s. The + ///shortest path tree used here is equal to the shortest path tree used in + ///\ref predNode(Node v). \pre \ref run() must be called before using + ///this function. + Edge pred(Node v) const { return (*predecessor)[v]; } + + ///Returns the 'previous node' of the shortest path tree. + + ///For a node \c v it returns the 'previous node' of the shortest path tree, + ///i.e. it returns the last but one node from a shortest path from the + ///root to \c /v. It is INVALID if \c v is unreachable from the root or if + ///\c v=s. The shortest path tree used here is equal to the shortest path + ///tree used in \ref pred(Node v). \pre \ref run() must be called before + ///using this function. + Node predNode(Node v) const { return (*pred_node)[v]; } + + ///Returns a reference to the NodeMap of distances. + + ///Returns a reference to the NodeMap of distances. \pre \ref run() must + ///be called before using this function. + const DistMap &distMap() const { return *distance;} + + ///Returns a reference to the shortest path tree map. + + ///Returns a reference to the NodeMap of the edges of the + ///shortest path tree. + ///\pre \ref run() must be called before using this function. + const PredMap &predMap() const { return *predecessor;} + + ///Returns a reference to the map of nodes of shortest paths. + + ///Returns a reference to the NodeMap of the last but one nodes of the + ///shortest path tree. + ///\pre \ref run() must be called before using this function. + const PredNodeMap &predNodeMap() const { return *pred_node;} + + ///Checks if a node is reachable from the root. + + ///Returns \c true if \c v is reachable from the root. + ///\warning the root node is reported to be unreached! + ///\todo Is this what we want? + ///\pre \ref run() must be called before using this function. + /// + bool reached(Node v) { return G->valid((*predecessor)[v]); } + + }; + + + // ********************************************************************** + // IMPLEMENTATIONS + // ********************************************************************** + +/// @} + +} //END OF NAMESPACE HUGO + +#endif + + diff -r 89d97db9c927 -r 625de6f1e766 src/work/deba/invalid.h --- a/src/work/deba/invalid.h Tue Jul 06 13:57:01 2004 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,33 +0,0 @@ -// -*- mode:C++ -*- - -#ifndef HUGO_INVALID_H -#define HUGO_INVALID_H - -///\file -///\brief Definition of INVALID. - -namespace hugo { - - /// Dummy type to make it easier to make invalid iterators. - - /// See \ref INVALID, how to use it. - - struct Invalid {}; - - /// Invalid iterators. - - /// \ref Invalid is a global type that converts to each iterator - /// in such a way that the value of the target iterator will be invalid. - - // It is also used to convert the \c INVALID constant to the - // node iterator that makes is possible to write - - //extern Invalid INVALID; - - //const Invalid &INVALID = *(Invalid *)0; - const Invalid INVALID = Invalid(); - -}; - -#endif - diff -r 89d97db9c927 -r 625de6f1e766 src/work/deba/list_graph.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/work/deba/list_graph.h Fri Jul 09 07:33:12 2004 +0000 @@ -0,0 +1,1305 @@ +// -*- mode:C++ -*- + +#ifndef HUGO_LIST_GRAPH_H +#define HUGO_LIST_GRAPH_H + +///\ingroup graphs +///\file +///\brief ListGraph, SymListGraph, NodeSet and EdgeSet classes. + +#include +#include + +#include "invalid.h" + +#include "vector_map_factory.h" +#include "map_registry.h" + +#include "map_defines.h" + +namespace hugo { + +/// \addtogroup graphs +/// @{ + + ///A list graph class. + + ///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 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() {} + }; + //Edges are double linked. + //The free edges are only single linked using the "next_in" field. + struct EdgeT + { + int head, tail; + int prev_in, prev_out; + int next_in, next_out; + //FIXME: is this necessary? + // EdgeT() : next_in(-1), next_out(-1) prev_in(-1), prev_out(-1) {} + }; + + 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; + + protected: + + public: + + class Node; + class Edge; + + typedef ListGraph Graph; + + public: + + class NodeIt; + class EdgeIt; + class OutEdgeIt; + class InEdgeIt; + + CREATE_MAP_REGISTRIES; + CREATE_MAPS(VectorMapFactory); + + public: + + 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) {} + + + int nodeNum() const { return nodes.size(); } //FIXME: What is this? + int edgeNum() const { return edges.size(); } //FIXME: What is this? + + ///Set the expected 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); }; + + ///\bug This function does something different than + ///its name would suggests... + int maxNodeId() const { return nodes.size(); } //FIXME: What is this? + ///\bug This function does something different than + ///its name would suggests... + int maxEdgeId() const { return edges.size(); } //FIXME: What is this? + + Node tail(Edge e) const { return edges[e.n].tail; } + Node head(Edge e) const { return edges[e.n].head; } + + Node aNode(OutEdgeIt e) const { return edges[e.n].tail; } + Node aNode(InEdgeIt e) const { return edges[e.n].head; } + + Node bNode(OutEdgeIt e) const { return edges[e.n].head; } + Node bNode(InEdgeIt e) const { return edges[e.n].tail; } + + 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; } + +// template< typename It > +// It first() const { It e; first(e); return e; } + +// template< typename It > +// It first(Node v) const { It e; first(e,v); return e; } + + bool valid(Edge e) const { return e.n!=-1; } + bool valid(Node n) const { return n.n!=-1; } + + void setInvalid(Edge &e) { e.n=-1; } + void setInvalid(Node &n) { n.n=-1; } + + template It getNext(It it) const + { It tmp(it); return next(tmp); } + + NodeIt& next(NodeIt& it) const { + 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 { + 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() { + 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; + } + + 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.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 + edge_maps.add(e); + + return e; + } + + 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 = n; + + //Update dynamic maps + Edge e; e.n=n; + } + + 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) { + edge_maps.erase(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 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) const; + 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 n NodeIt. + NodeIt(const ListGraph& G, const Node &n) : Node(n) { } + }; + + class Edge { + friend class ListGraph; + template friend class EdgeMap; + + //template friend class SymListGraph::SymEdgeMap; + //friend Edge SymListGraph::opposite(Edge) const; + + friend class Node; + friend class NodeIt; + protected: + int n; + friend int ListGraph::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 nodes; + //The first node + int first_node; + //The first free node + int first_free_node; + + protected: + + template class DynMapBase + { + protected: + const NodeSet* G; + public: + virtual void add(const Key k) = 0; + virtual void erase(const Key k) = 0; + DynMapBase(const NodeSet &_G) : G(&_G) {} + virtual ~DynMapBase() {} + friend class NodeSet; + }; + + public: + template class EdgeMap; + template class NodeMap; + + class Node; + class Edge; + + // protected: + // HELPME: + protected: + ///\bug It must be public because of SymEdgeMap. + /// + mutable std::vector * > dyn_node_maps; + //mutable std::vector * > dyn_edge_maps; + + public: + + class NodeIt; + class EdgeIt; + class OutEdgeIt; + class InEdgeIt; + + template class NodeMap; + template class EdgeMap; + + 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) {} + + ~NodeSet() + { + for(std::vector * >::iterator i=dyn_node_maps.begin(); + i!=dyn_node_maps.end(); ++i) (**i).G=NULL; + //for(std::vector * >::iterator i=dyn_edge_maps.begin(); + // i!=dyn_edge_maps.end(); ++i) (**i).G=NULL; + } + + int nodeNum() const { return nodes.size(); } //FIXME: What is this? + int edgeNum() const { return 0; } //FIXME: What is this? + + ///\bug This function does something different than + ///its name would suggests... + int maxNodeId() const { return nodes.size(); } //FIXME: What is this? + ///\bug This function does something different than + ///its name would suggests... + int maxEdgeId() const { return 0; } //FIXME: What is this? + + Node tail(Edge e) const { return INVALID; } + Node head(Edge e) const { return INVALID; } + + Node aNode(OutEdgeIt e) const { return INVALID; } + Node aNode(InEdgeIt e) const { return INVALID; } + + Node bNode(OutEdgeIt e) const { return INVALID; } + Node bNode(InEdgeIt 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; } + +// template< typename It > +// It first() const { It e; first(e); return e; } + +// template< typename It > +// It first(Node v) const { It e; first(e,v); return e; } + + bool valid(Edge e) const { return false; } + bool valid(Node n) const { return n.n!=-1; } + + void setInvalid(Edge &e) { } + void setInvalid(Node &n) { n.n=-1; } + + template It getNext(It it) const + { It tmp(it); return next(tmp); } + + NodeIt& next(NodeIt& it) const { + it.n=nodes[it.n].next; + return it; + } + OutEdgeIt& next(OutEdgeIt& it) const { return it; } + InEdgeIt& next(InEdgeIt& it) const { return it; } + EdgeIt& next(EdgeIt& it) const { return it; } + + int id(Node v) const { return v.n; } + int id(Edge e) const { return -1; } + + /// 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() { + 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 * >::iterator i=dyn_node_maps.begin(); + i!=dyn_node_maps.end(); ++i) (**i).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 + for(std::vector * >::iterator i=dyn_node_maps.begin(); + i!=dyn_node_maps.end(); ++i) (**i).erase(nn); + } + + ///\bug Dynamic maps must be updated! + /// + void 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) const; + 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 n NodeIt. + NodeIt(const NodeSet& G, const Node &n) : Node(n) { } + + }; + + class Edge { + //friend class NodeSet; + //template friend class EdgeMap; + + //template friend class SymNodeSet::SymEdgeMap; + //friend Edge SymNodeSet::opposite(Edge) const; + + // friend class Node; + // friend class NodeIt; + protected: + //friend int NodeSet::id(Edge e) const; + // Edge(int nn) {} + 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;} + ///\bug This is a workaround until somebody tells me how to + ///make class \c SymNodeSet::SymEdgeMap friend of Edge + // int idref() {return -1;} + // int idref() const {return -1;} + }; + + class EdgeIt : public Edge { + //friend class NodeSet; + public: + EdgeIt(const NodeSet& G) : Edge() { } + EdgeIt (Invalid i) : Edge(i) { } + EdgeIt() : Edge() { } + ///\bug This is a workaround until somebody tells me how to + ///make class \c SymNodeSet::SymEdgeMap friend of Edge + // int idref() {return -1;} + }; + + class OutEdgeIt : public Edge { + friend class NodeSet; + public: + OutEdgeIt() : Edge() { } + OutEdgeIt (Invalid i) : Edge(i) { } + OutEdgeIt(const NodeSet& G,const Node v) : Edge() {} + }; + + class InEdgeIt : public Edge { + friend class NodeSet; + public: + InEdgeIt() : Edge() { } + InEdgeIt (Invalid i) : Edge(i) { } + InEdgeIt(const NodeSet& G,Node v) :Edge() {} + }; + + template class NodeMap : public DynMapBase + { + std::vector container; + + public: + typedef T ValueType; + typedef Node KeyType; + + NodeMap(const NodeSet &_G) : + DynMapBase(_G), container(_G.maxNodeId()) + { + G->dyn_node_maps.push_back(this); + } + NodeMap(const NodeSet &_G,const T &t) : + DynMapBase(_G), container(_G.maxNodeId(),t) + { + G->dyn_node_maps.push_back(this); + } + + NodeMap(const NodeMap &m) : + DynMapBase(*m.G), container(m.container) + { + G->dyn_node_maps.push_back(this); + } + + template friend class NodeMap; + + ///\todo It can copy between different types. + /// + template NodeMap(const NodeMap &m) : + DynMapBase(*m.G), container(m.container.size()) + { + G->dyn_node_maps.push_back(this); + typename std::vector::const_iterator i; + for(typename std::vector::const_iterator i=m.container.begin(); + i!=m.container.end(); + i++) + container.push_back(*i); + } + ~NodeMap() + { + if(G) { + std::vector* >::iterator i; + for(i=G->dyn_node_maps.begin(); + i!=G->dyn_node_maps.end() && *i!=this; ++i) ; + //if(*i==this) G->dyn_node_maps.erase(i); //FIXME: Way too slow... + //A better way to do that: (Is this really important?) + if(*i==this) { + *i=G->dyn_node_maps.back(); + G->dyn_node_maps.pop_back(); + } + } + } + + void add(const Node k) + { + if(k.n>=int(container.size())) container.resize(k.n+1); + } + + void erase(const Node) { } + + void set(Node n, T a) { container[n.n]=a; } + //'T& operator[](Node n)' would be wrong here + typename std::vector::reference + operator[](Node n) { return container[n.n]; } + //'const T& operator[](Node n)' would be wrong here + typename std::vector::const_reference + operator[](Node n) const { return container[n.n]; } + + ///\warning There is no safety check at all! + ///Using operator = between maps attached to different graph may + ///cause serious problem. + ///\todo Is this really so? + ///\todo It can copy between different types. + const NodeMap& operator=(const NodeMap &m) + { + container = m.container; + return *this; + } + template + const NodeMap& operator=(const NodeMap &m) + { + std::copy(m.container.begin(), m.container.end(), container.begin()); + return *this; + } + + void update() {} //Useless for Dynamic Maps + void update(T a) {} //Useless for Dynamic Maps + }; + + template class EdgeMap + { + public: + typedef T ValueType; + typedef Edge KeyType; + + EdgeMap(const NodeSet &) { } + EdgeMap(const NodeSet &,const T &) { } + EdgeMap(const EdgeMap &) { } + // template friend class EdgeMap; + + ///\todo It can copy between different types. + /// + template EdgeMap(const EdgeMap &) { } + ~EdgeMap() { } + + void add(const Edge ) { } + void erase(const Edge) { } + + void set(Edge, T) { } + //T get(Edge n) const { return container[n.n]; } + ValueType &operator[](Edge) { return *((T*)(NULL)); } + const ValueType &operator[](Edge) const { return *((T*)(NULL)); } + + const EdgeMap& operator=(const EdgeMap &) { return *this; } + + template + const EdgeMap& operator=(const EdgeMap &m) { return *this; } + + void update() {} + void update(T a) {} + }; + }; + + + + ///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 with \ref GraphSkeleton. + /// + ///It conforms to the graph interface documented under + ///the description of \ref GraphSkeleton. + ///\sa \ref GraphSkeleton. + ///\sa \ref NodeSet. + template + class EdgeSet { + + typedef GG NodeGraphType; + + NodeGraphType &G; + + public: + class Node; + int id(Node v) const; + + class Node : public NodeGraphType::Node { + friend class EdgeSet; + // template friend class NodeMap; + + friend class Edge; + friend class OutEdgeIt; + friend class InEdgeIt; + friend class SymEdge; + + public: + friend int EdgeSet::id(Node v) const; + // Node(int nn) {n=nn;} + 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 (Invalid i) : NodeGraphType::NodeIt(i) {} + NodeIt(const EdgeSet& _G) : NodeGraphType::NodeIt(_G.G) { } + NodeIt(const typename NodeGraphType::NodeIt &n) + : NodeGraphType::NodeIt(n) {} + ///\todo Undocumented conversion Node -\> NodeIt. + NodeIt(const EdgeSet& _G, const Node &n) + : NodeGraphType::NodeIt(_G.G,n) { } + + operator Node() { return Node(*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; + + protected: + + template class DynMapBase + { + protected: + const EdgeSet* G; + public: + virtual void add(const Key k) = 0; + virtual void erase(const Key k) = 0; + DynMapBase(const EdgeSet &_G) : G(&_G) {} + virtual ~DynMapBase() {} + friend class EdgeSet; + }; + + public: + //template class NodeMap; + template class EdgeMap; + + class Node; + class Edge; + + // protected: + // HELPME: + protected: + // mutable std::vector * > dyn_node_maps; + ///\bug It must be public because of SymEdgeMap. + /// + mutable std::vector * > dyn_edge_maps; + + public: + + class NodeIt; + class EdgeIt; + class OutEdgeIt; + class InEdgeIt; + + template class NodeMap; + template class EdgeMap; + + public: + + ///Constructor + + ///Construates a new graph based on the nodeset of an existing one. + ///\param _G the base graph. + ///\todo It looks like a copy constructor, but it isn't. + 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. + EdgeSet(const EdgeSet &_g) : G(_g.G), nodes(_g.G), edges(_g.edges), + first_free_edge(_g.first_free_edge) { } + + ~EdgeSet() + { + // for(std::vector * >::iterator i=dyn_node_maps.begin(); + // i!=dyn_node_maps.end(); ++i) (**i).G=NULL; + for(typename std::vector * >::iterator + i=dyn_edge_maps.begin(); + i!=dyn_edge_maps.end(); ++i) (**i).G=NULL; + } + + int nodeNum() const { return G.nodeNum(); } //FIXME: What is this? + int edgeNum() const { return edges.size(); } //FIXME: What is this? + + ///\bug This function does something different than + ///its name would suggests... + int maxNodeId() const { return G.maxNodeId(); } //FIXME: What is this? + ///\bug This function does something different than + ///its name would suggests... + int maxEdgeId() const { return edges.size(); } //FIXME: What is this? + + Node tail(Edge e) const { return edges[e.n].tail; } + Node head(Edge e) const { return edges[e.n].head; } + + Node aNode(OutEdgeIt e) const { return edges[e.n].tail; } + Node aNode(InEdgeIt e) const { return edges[e.n].head; } + + Node bNode(OutEdgeIt e) const { return edges[e.n].head; } + Node bNode(InEdgeIt e) const { return edges[e.n].tail; } + + 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; } + +// template< typename It > +// It first() const { It e; first(e); return e; } + +// template< typename It > +// It first(Node v) const { It e; first(e,v); return e; } + + bool valid(Edge e) const { return e.n!=-1; } + bool valid(Node n) const { return G.valid(n); } + + void setInvalid(Edge &e) { e.n=-1; } + void setInvalid(Node &n) { G.setInvalid(n); } + + template It getNext(It it) const + { It tmp(it); return next(tmp); } + + NodeIt& next(NodeIt& it) const { G.next(it); 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 { + if(edges[it.n].next_in!=-1) { + it.n=edges[it.n].next_in; + } + else { + NodeIt n(*this,edges[it.n].head); + for(n=next(n); + valid(n) && nodes[n].first_in == -1; + next(n)) ; + it.n = (valid(n))?-1:nodes[n].first_in; + } + return it; + } + + int id(Edge e) const { 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 + for(typename std::vector * >::iterator + i=dyn_edge_maps.begin(); + i!=dyn_edge_maps.end(); ++i) (**i).add(e); + + return e; + } + + 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(typename std::vector * >::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); +// } + + void erase(Edge e) { eraseEdge(e.n); } + + ///Clear all edges. (Doesn't clear the nodes!) + void clear() { + edges.clear(); + first_free_edge=-1; + } + + +// //\bug Dynamic maps must be updated! +// // +// void clear() { +// nodes.clear();edges.clear(); +// first_node=first_free_node=first_free_edge=-1; +// } + + public: + template class EdgeMap; + + /// + class Edge { + public: + friend class EdgeSet; + template friend class EdgeMap; + + friend class Node; + friend class NodeIt; + public: + ///\bug It shoud be at least protected + /// + int n; + protected: + 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; + + + public: + EdgeIt(const EdgeSet& G) : Edge() { + // typename NodeGraphType::Node m; + NodeIt m; + for(G.first(m); + G.valid(m) && G.nodes[m].first_in == -1; G.next(m)); + //AJJAJ! This is a non sense!!!!!!! + this->n = G.valid(m)?-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 SymEdgeSet::SymEdgeMap friend of Edge + int &idref() {return this->n;} + }; + + class OutEdgeIt : public Edge { + friend class EdgeSet; + public: + OutEdgeIt() : Edge() { } + OutEdgeIt (Invalid i) : Edge(i) { } + + OutEdgeIt(const EdgeSet& G,const Node v) : Edge(G.nodes[v].first_out) { } + }; + + class InEdgeIt : public Edge { + friend class EdgeSet; + public: + InEdgeIt() : Edge() { } + InEdgeIt (Invalid i) : Edge(i) { } + InEdgeIt(const EdgeSet& G,Node v) :Edge(G.nodes[v].first_in) { } + }; + + template class NodeMap : + public NodeGraphType::template NodeMap + { + //This is a must, the constructors need it. + typedef typename NodeGraphType::template NodeMap ParentNodeMap; + public: + NodeMap(const EdgeSet &_G) : ParentNodeMap(_G.G) { } + NodeMap(const EdgeSet &_G,const T &t) : ParentNodeMap(_G.G,t) { } + //It is unnecessary + NodeMap(const typename NodeGraphType::template NodeMap &m) : + ParentNodeMap(m) { } + + ///\todo It can copy between different types. + /// + template + NodeMap(const typename NodeGraphType::template NodeMap &m) + : ParentNodeMap(m) { } + }; + + /// + template class EdgeMap : public DynMapBase + { + protected: + public: + ///\bug It should be at least protected + /// + std::vector container; + + public: + typedef T ValueType; + typedef Edge KeyType; + + EdgeMap(const EdgeSet &_G) : + DynMapBase(_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 EdgeSet &_G,const T &t) : + DynMapBase(_G), container(_G.maxEdgeId(),t) + { + G->dyn_edge_maps.push_back(this); + } + EdgeMap(const EdgeMap &m) : + DynMapBase(*m.G), container(m.container) + { + G->dyn_edge_maps.push_back(this); + } + + template friend class EdgeMap; + + ///\todo It can copy between different types. + /// + template EdgeMap(const EdgeMap &m) : + DynMapBase(*m.G), container(m.container.size()) + { + G->dyn_edge_maps.push_back(this); + typename std::vector::const_iterator i; + for(typename std::vector::const_iterator i=m.container.begin(); + i!=m.container.end(); + i++) + container.push_back(*i); + } + ~EdgeMap() + { + if(G) { + typename std::vector* >::iterator i; + for(i=G->dyn_edge_maps.begin(); + i!=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=G->dyn_edge_maps.back(); + G->dyn_edge_maps.pop_back(); + } + } + } + + void add(const Edge k) + { + if(k.n>=int(container.size())) container.resize(k.n+1); + } + void erase(const Edge) { } + + ///\bug This doesn't work. Why? + /// void set(Edge n, T a) { container[n.n]=a; } + void set(Edge n, T a) { container[G->id(n)]=a; } + //T get(Edge n) const { return container[n.n]; } + typename std::vector::reference + ///\bug This doesn't work. Why? + /// operator[](Edge n) { return container[n.n]; } + operator[](Edge n) { return container[G->id(n)]; } + typename std::vector::const_reference + ///\bug This doesn't work. Why? + /// operator[](Edge n) const { return container[n.n]; } + operator[](Edge n) const { return container[G->id(n)]; } + + ///\warning There is no safety check at all! + ///Using operator = between maps attached to different graph may + ///cause serious problem. + ///\todo Is this really so? + ///\todo It can copy between different types. + const EdgeMap& operator=(const EdgeMap &m) + { + container = m.container; + return *this; + } + + template friend class EdgeMap; + + template + const EdgeMap& operator=(const EdgeMap &m) + { + std::copy(m.container.begin(), m.container.end(), container.begin()); + return *this; + } + + void update() {} //Useless for DynMaps + void update(T a) {} //Useless for DynMaps + }; + + }; + + template + inline int EdgeSet::id(Node v) const { return G.id(v); } + +/// @} + +} //namespace hugo + +#endif //HUGO_LIST_GRAPH_H diff -r 89d97db9c927 -r 625de6f1e766 src/work/deba/main.cpp --- a/src/work/deba/main.cpp Tue Jul 06 13:57:01 2004 +0000 +++ b/src/work/deba/main.cpp Fri Jul 09 07:33:12 2004 +0000 @@ -1,6 +1,6 @@ #include #include -#include "test_graph.h" +#include "list_graph.h" using namespace std; using namespace hugo; diff -r 89d97db9c927 -r 625de6f1e766 src/work/deba/test_graph.h --- a/src/work/deba/test_graph.h Tue Jul 06 13:57:01 2004 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,539 +0,0 @@ -// -*- c++ -*- -#ifndef HUGO_LIST_GRAPH_H -#define HUGO_LIST_GRAPH_H - -#include -#include - -#include "invalid.h" - -#include "map_registry.h" -#include "array_map_factory.h" - -#include "map_defines.h" - -namespace hugo { - - template - int count(It it) { - int i=0; - for( ; it.valid(); ++it) { ++i; } - return i; - } - - class ListGraph { - class node_item; - class edge_item; - public: - class Node; - class NodeIt; - class Edge; - class EdgeIt; - class OutEdgeIt; - class InEdgeIt; - class SymEdgeIt; - - typedef ListGraph Graph; - - CREATE_MAP_REGISTRIES; - CREATE_MAPS(ArrayMapFactory); - - private: - - int node_id; - int edge_id; - int _node_num; - int _edge_num; - - node_item* _first_node; - node_item* _last_node; - - class node_item { - friend class ListGraph; - template friend class NodeMap; - - friend class Node; - friend class NodeIt; - friend class Edge; - friend class EdgeIt; - friend class OutEdgeIt; - friend class InEdgeIt; - friend class SymEdgeIt; - friend std::ostream& operator<<(std::ostream& os, const Node& i); - friend std::ostream& operator<<(std::ostream& os, const Edge& i); - //ListGraph* G; - int id; - edge_item* _first_out_edge; - edge_item* _last_out_edge; - edge_item* _first_in_edge; - edge_item* _last_in_edge; - node_item* _next_node; - node_item* _prev_node; - public: - node_item() { } - }; - - class edge_item { - friend class ListGraph; - template friend class EdgeMap; - - friend class Node; - friend class NodeIt; - friend class Edge; - friend class EdgeIt; - friend class OutEdgeIt; - friend class InEdgeIt; - friend class SymEdgeIt; - friend std::ostream& operator<<(std::ostream& os, const Edge& i); - //ListGraph* G; - int id; - node_item* _tail; - node_item* _head; - edge_item* _next_out; - edge_item* _prev_out; - edge_item* _next_in; - edge_item* _prev_in; - public: - edge_item() { } - }; - - node_item* _add_node() { - node_item* p=new node_item; - p->id=node_id++; - p->_first_out_edge=0; - p->_last_out_edge=0; - p->_first_in_edge=0; - p->_last_in_edge=0; - p->_prev_node=_last_node; - p->_next_node=0; - if (_last_node) _last_node->_next_node=p; - _last_node=p; - if (!_first_node) _first_node=p; - - ++_node_num; - return p; - } - - edge_item* _add_edge(node_item* _tail, node_item* _head) { - edge_item* e=new edge_item; - e->id=edge_id++; - e->_tail=_tail; - e->_head=_head; - - e->_prev_out=_tail->_last_out_edge; - if (_tail->_last_out_edge) (_tail->_last_out_edge)->_next_out=e; - _tail->_last_out_edge=e; - if (!_tail->_first_out_edge) _tail->_first_out_edge=e; - e->_next_out=0; - - e->_prev_in=_head->_last_in_edge; - if (_head->_last_in_edge) (_head->_last_in_edge)->_next_in=e; - _head->_last_in_edge=e; - if (!_head->_first_in_edge) { _head->_first_in_edge=e; } - e->_next_in=0; - - ++_edge_num; - return e; - } - - //deletes a node which has no out edge and no in edge - void _delete_node(node_item* v) { - if (v->_next_node) (v->_next_node)->_prev_node=v->_prev_node; else - _last_node=v->_prev_node; - if (v->_prev_node) (v->_prev_node)->_next_node=v->_next_node; else - _first_node=v->_next_node; - - delete v; - --_node_num; - } - - void _delete_edge(edge_item* e) { - if (e->_next_out) (e->_next_out)->_prev_out=e->_prev_out; else - (e->_tail)->_last_out_edge=e->_prev_out; - if (e->_prev_out) (e->_prev_out)->_next_out=e->_next_out; else - (e->_tail)->_first_out_edge=e->_next_out; - if (e->_next_in) (e->_next_in)->_prev_in=e->_prev_in; else - (e->_head)->_last_in_edge=e->_prev_in; - if (e->_prev_in) (e->_prev_in)->_next_in=e->_next_in; else - (e->_head)->_first_in_edge=e->_next_in; - - delete e; - --_edge_num; - } - - void _set_tail(edge_item* e, node_item* _tail) { - if (e->_next_out) (e->_next_out)->_prev_out=e->_prev_out; else - (e->_tail)->_last_out_edge=e->_prev_out; - if (e->_prev_out) (e->_prev_out)->_next_out=e->_next_out; else - (e->_tail)->_first_out_edge=e->_next_out; - - e->_tail=_tail; - - e->_prev_out=_tail->_last_out_edge; - if (_tail->_last_out_edge) (_tail->_last_out_edge)->_next_out=e; - _tail->_last_out_edge=e; - if (!_tail->_first_out_edge) _tail->_first_out_edge=e; - e->_next_out=0; - } - - void _set_head(edge_item* e, node_item* _head) { - if (e->_next_in) (e->_next_in)->_prev_in=e->_prev_in; else - (e->_head)->_last_in_edge=e->_prev_in; - if (e->_prev_in) (e->_prev_in)->_next_in=e->_next_in; else - (e->_head)->_first_in_edge=e->_next_in; - - e->_head=_head; - - e->_prev_in=_head->_last_in_edge; - if (_head->_last_in_edge) (_head->_last_in_edge)->_next_in=e; - _head->_last_in_edge=e; - if (!_head->_first_in_edge) { _head->_first_in_edge=e; } - e->_next_in=0; - } - - public: - - /* default constructor */ - - ListGraph() : node_id(0), edge_id(0), _node_num(0), _edge_num(0), _first_node(0), _last_node(0){ } - - ~ListGraph() { - while (first().valid()) erase(first()); - } - - int nodeNum() const { return _node_num; } - int edgeNum() const { return _edge_num; } - - /* functions to construct iterators from the graph, or from each other */ - - //NodeIt firstNode() const { return NodeIt(*this); } - //EdgeIt firstEdge() const { return EdgeIt(*this); } - - //OutEdgeIt firstOutEdge(const Node v) const { return OutEdgeIt(v); } - //InEdgeIt firstInEdge(const Node v) const { return InEdgeIt(v); } - //SymEdgeIt firstSymEdge(const Node v) const { return SymEdgeIt(v); } - Node tail(Edge e) const { return e.tailNode(); } - Node head(Edge e) const { return e.headNode(); } - - Node aNode(const OutEdgeIt& e) const { return e.aNode(); } - Node aNode(const InEdgeIt& e) const { return e.aNode(); } - Node aNode(const SymEdgeIt& e) const { return e.aNode(); } - - Node bNode(const OutEdgeIt& e) const { return e.bNode(); } - Node bNode(const InEdgeIt& e) const { return e.bNode(); } - Node bNode(const SymEdgeIt& e) const { return e.bNode(); } - - //Node invalid_node() { return Node(); } - //Edge invalid_edge() { return Edge(); } - //OutEdgeIt invalid_out_edge() { return OutEdgeIt(); } - //InEdgeIt invalid_in_edge() { return InEdgeIt(); } - //SymEdgeIt invalid_sym_edge() { return SymEdgeIt(); } - - /* same methods in other style */ - /* for experimental purpose */ - - NodeIt& /*getF*/first(NodeIt& v) const { - v=NodeIt(*this); return v; } - EdgeIt& /*getF*/first(EdgeIt& e) const { - e=EdgeIt(*this); return e; } - OutEdgeIt& /*getF*/first(OutEdgeIt& e, Node v) const { - e=OutEdgeIt(*this, v); return e; } - InEdgeIt& /*getF*/first(InEdgeIt& e, Node v) const { - e=InEdgeIt(*this, v); return e; } - SymEdgeIt& /*getF*/first(SymEdgeIt& e, Node v) const { - e=SymEdgeIt(*this, v); return e; } - //void getTail(Node& n, const Edge& e) const { n=tail(e); } - //void getHead(Node& n, const Edge& e) const { n=head(e); } - - //void getANode(Node& n, const OutEdgeIt& e) const { n=e.aNode(); } - //void getANode(Node& n, const InEdgeIt& e) const { n=e.aNode(); } - //void getANode(Node& n, const SymEdgeIt& e) const { n=e.aNode(); } - //void getBNode(Node& n, const OutEdgeIt& e) const { n=e.bNode(); } - //void getBNode(Node& n, const InEdgeIt& e) const { n=e.bNode(); } - //void getBNode(Node& n, const SymEdgeIt& e) const { n=e.bNode(); } - //void get_invalid(Node& n) { n=Node(); } - //void get_invalid(Edge& e) { e=Edge(); } - //void get_invalid(OutEdgeIt& e) { e=OutEdgeIt(); } - //void get_invalid(InEdgeIt& e) { e=InEdgeIt(); } - //void get_invalid(SymEdgeIt& e) { e=SymEdgeIt(); } - - template< typename It > - It first() const { - It e; - /*getF*/first(e); - return e; - } - - template< typename It > - It first(Node v) const { - It e; - /*getF*/first(e, v); - return e; - } - - bool valid(Node n) const { return n.valid(); } - bool valid(Edge e) const { return e.valid(); } - - template It getNext(It it) const { - It tmp(it); return next(tmp); } - template It& next(It& it) const { return ++it; } - - - /* for getting id's of graph objects */ - /* these are important for the implementation of property vectors */ - - int id(Node v) const { return v.node->id; } - int id(Edge e) const { return e.edge->id; } - - /* adding nodes and edges */ - - Node addNode() { - Node n = _add_node(); - node_maps.add(n); - return n; - } - Edge addEdge(Node u, Node v) { - Edge e = _add_edge(u.node, v.node); - edge_maps.add(e); - return e; - } - - void erase(Node i) { - node_maps.erase(i); - while (first(i).valid()) erase(first(i)); - while (first(i).valid()) erase(first(i)); - _delete_node(i.node); - } - - void erase(Edge e) { - edge_maps.erase(e); - _delete_edge(e.edge); - } - - void clear() { - while (first().valid()) erase(first()); - } - - void setTail(Edge e, Node tail) { - _set_tail(e.edge, tail.node); - } - - void setHead(Edge e, Node head) { - _set_head(e.edge, head.node); - } - - /* stream operations, for testing purpose */ - - friend std::ostream& operator<<(std::ostream& os, const Node& i) { - os << i.node->id; return os; - } - friend std::ostream& operator<<(std::ostream& os, const Edge& i) { - os << "(" << i.edge->_tail->id << "--" << i.edge->id << "->" << i.edge->_head->id << ")"; - return os; - } - - class Node { - friend class ListGraph; - template friend class NodeMap; - - friend class Edge; - friend class OutEdgeIt; - friend class InEdgeIt; - friend class SymEdgeIt; - //public: //FIXME: It is required by op= of NodeIt - protected: - node_item* node; - protected: - friend int ListGraph::id(Node v) const; - public: - Node() /*: node(0)*/ { } - Node(const Invalid&) : node(0) { } - protected: - Node(node_item* _node) : node(_node) { } - bool valid() const { return (node); } - public: - //void makeInvalid() { node=0; } - friend bool operator==(Node u, Node v) { return v.node==u.node; } - friend bool operator!=(Node u, Node v) { return v.node!=u.node; } - friend std::ostream& operator<<(std::ostream& os, const Node& i); - }; - - class NodeIt : public Node { - friend class ListGraph; - //protected: - public: //for everybody but marci - NodeIt(const ListGraph& G) : Node(G._first_node) { } - public: - NodeIt() : Node() { } - NodeIt(const Invalid& i) : Node(i) { } - protected: - NodeIt(node_item* v) : Node(v) { } - NodeIt& operator++() { node=node->_next_node; return *this; } - //FIXME:: - // NodeIt& operator=(const Node& e) - // { node=e.node; return *this; } - }; - - class Edge { - friend class ListGraph; - template friend class EdgeMap; - - friend class Node; - friend class NodeIt; - protected: - edge_item* edge; - friend int ListGraph::id(Edge e) const; - public: - Edge() /*: edge(0)*/ { } - Edge(const Invalid&) : edge(0) { } - //Edge() { } - protected: - Edge(edge_item* _edge) : edge(_edge) { } - bool valid() const { return (edge); } - public: - //void makeInvalid() { edge=0; } - friend bool operator==(Edge u, Edge v) { return v.edge==u.edge; } - friend bool operator!=(Edge u, Edge v) { return v.edge!=u.edge; } - protected: - Node tailNode() const { return Node(edge->_tail); } - Node headNode() const { return Node(edge->_head); } - public: - friend std::ostream& operator<<(std::ostream& os, const Edge& i); - }; - - class EdgeIt : public Edge { - friend class ListGraph; - //protected: - public: //for alpar - EdgeIt(const ListGraph& G) { - node_item* v=G._first_node; - if (v) edge=v->_first_out_edge; else edge=0; - while (v && !edge) { v=v->_next_node; if (v) edge=v->_first_out_edge; } - } - public: - EdgeIt() : Edge() { } - EdgeIt(const Invalid& i) : Edge(i) { } - protected: - EdgeIt(edge_item* _e) : Edge(_e) { } - EdgeIt& operator++() { - node_item* v=edge->_tail; - edge=edge->_next_out; - while (v && !edge) { v=v->_next_node; if (v) edge=v->_first_out_edge; } - return *this; - } - }; - - class OutEdgeIt : public Edge { - friend class ListGraph; - //node_item* v; - //protected: - protected: //for alpar - OutEdgeIt(const Node& _v) /*: v(_v.node)*/ { edge=_v.node->_first_out_edge; } - public: - OutEdgeIt() : Edge()/*, v(0)*/ { } - OutEdgeIt(const Invalid& i) : Edge(i) { } - OutEdgeIt(const ListGraph&, Node _v) /*: v(_v.node)*/ { edge=_v.node->_first_out_edge; } - protected: - OutEdgeIt& operator++() { edge=edge->_next_out; return *this; } - protected: - Node aNode() const { return Node(edge->_tail); } - Node bNode() const { return Node(edge->_head); } - }; - - class InEdgeIt : public Edge { - friend class ListGraph; - //node_item* v; - //protected: - protected: //for alpar - InEdgeIt(const Node& _v) /*: v(_v.node)*/ { edge=_v.node->_first_in_edge; } - public: - InEdgeIt() : Edge()/*, v(0)*/ { } - InEdgeIt(const Invalid& i) : Edge(i) { } - InEdgeIt(const ListGraph&, Node _v) /*: v(_v.node)*/ { edge=_v.node->_first_in_edge; } - protected: - InEdgeIt& operator++() { edge=edge->_next_in; return *this; } - protected: - Node aNode() const { return Node(edge->_head); } - Node bNode() const { return Node(edge->_tail); } - }; - - class SymEdgeIt : public Edge { - friend class ListGraph; - bool out_or_in; //1 iff out, 0 iff in - //node_item* v; - //protected: - public: //for alpar - SymEdgeIt(const Node& _v) /*: v(_v.node)*/ { - out_or_in=1; - edge=_v.node->_first_out_edge; - if (!edge) { edge=_v.node->_first_in_edge; out_or_in=0; } - } - public: - SymEdgeIt() : Edge() /*, v(0)*/ { } - SymEdgeIt(const Invalid& i) : Edge(i) { } - SymEdgeIt(const ListGraph&, Node _v) /*: v(_v.node)*/ { - out_or_in=1; - edge=_v.node->_first_out_edge; - if (!edge) { edge=_v.node->_first_in_edge; out_or_in=0; } - } - protected: - SymEdgeIt& operator++() { - if (out_or_in) { - node_item* v=edge->_tail; - edge=edge->_next_out; - if (!edge) { out_or_in=0; edge=v->_first_in_edge; } - } else { - edge=edge->_next_in; - } - return *this; - } - protected: - Node aNode() const { - return (out_or_in) ? Node(edge->_tail) : Node(edge->_head); } - Node bNode() const { - return (out_or_in) ? Node(edge->_head) : Node(edge->_tail); } - }; - - }; - - // template< typename T > - // T ListGraph::first() const { - // std::cerr << "Invalid use of template T ListGraph::first();" << std::endl; - // return T(); - // } - - // template<> - // ListGraph::NodeIt ListGraph::first() const { - // return firstNode(); - // } - - // template<> - // ListGraph::EdgeIt ListGraph::first() const { - // return firstEdge(); - // } - - // template< typename T > - // T ListGraph::first(ListGraph::Node v) const { - // std::cerr << "Invalid use of template T ListGraph::first(ListGRaph::Node);" << std::endl; - // return T(); - // } - - // template<> - // ListGraph::OutEdgeIt ListGraph::first(const ListGraph::Node v) const { - // return firstOutEdge(v); - // } - - // template<> - // ListGraph::InEdgeIt ListGraph::first(const ListGraph::Node v) const { - // return firstInEdge(v); - // } - - // template<> - // ListGraph::SymEdgeIt ListGraph::first(const ListGraph::Node v) const { - // return firstSymEdge(v); - // } - - -} //namespace hugo - -#endif //HUGO_LIST_GRAPH_H diff -r 89d97db9c927 -r 625de6f1e766 src/work/deba/vector_map_factory.h --- a/src/work/deba/vector_map_factory.h Tue Jul 06 13:57:01 2004 +0000 +++ b/src/work/deba/vector_map_factory.h Fri Jul 09 07:33:12 2004 +0000 @@ -3,25 +3,25 @@ #include -#include "map_registry.h" - namespace hugo { template - class VectorMapFactory { - public: + class VectorMapFactory { + public: typedef typename MapRegistry::Graph Graph; typedef typename MapRegistry::Key Key; typedef typename MapRegistry::KeyIt KeyIt; typedef typename MapRegistry::MapBase MapBase; + template class Map : public MapBase { public: typedef V Value; + typedef std::vector Container; Map() {} Map(Graph& g, MapRegistry& r) : MapBase(g, r) { @@ -34,21 +34,16 @@ } - Value& operator[](const Key& key) { + typename Container::reference operator[](const Key& key) { int id = graph->id(key); return container[id]; } - const Value& operator[](const Key& key) const { + typename Container::const_reference operator[](const Key& key) const { int id = graph->id(key); return container[id]; } - const Value& get(const Key& key) const { - int id = graph->id(key); - return container[id]; - } - void set(const Key& key, const Value& val) { int id = graph->id(key); container[id] = val; @@ -63,11 +58,37 @@ void erase(const Key& key) {} + class const_iterator { + + private: + + }; + + class iterator { + public: + iterator() {} + + std::pair operator*() { + return std::pair(static_cast(it), map[it]); + } + + iterator& operator++() { ++it; return *this; } + iterator operator++(int) { iterator tmp(it); ++it; return tmp; } + private: + Map& map; + KeyIt it; + }; + private: typedef std::vector Container; Container container; + + }; + + + }; }