Open
Graph Drawing
Framework

 v.2010.10
 

Graph_d.h

Go to the documentation of this file.
00001 /*
00002  * $Revision: 2047 $
00003  * 
00004  * last checkin:
00005  *   $Author: klein $ 
00006  *   $Date: 2010-10-13 17:12:21 +0200 (Wed, 13 Oct 2010) $ 
00007  ***************************************************************/
00008  
00056 #ifdef _MSC_VER
00057 #pragma once
00058 #endif
00059 
00060 #ifndef OGDF_GRAPH_D_H
00061 #define OGDF_GRAPH_D_H
00062 
00063 
00064 #include <ogdf/basic/List.h>
00065 
00066 
00067 namespace ogdf {
00068 
00069 //
00070 // in embedded graphs, adjacency lists are given in clockwise order.
00071 //
00072 
00073 
00074 class OGDF_EXPORT Graph;
00075 class OGDF_EXPORT NodeElement;
00076 class OGDF_EXPORT EdgeElement;
00077 class OGDF_EXPORT AdjElement;
00078 class OGDF_EXPORT FaceElement;
00079 class OGDF_EXPORT GraphListBase;
00080 class OGDF_EXPORT ClusterElement;
00081 
00082 
00084 
00089 class OGDF_EXPORT GraphElement {
00090     friend class Graph;
00091     friend class GraphListBase;
00092 
00093 protected:
00094     GraphElement *m_next; 
00095     GraphElement *m_prev; 
00096 
00097     OGDF_NEW_DELETE
00098 }; // class GraphElement
00099 
00100 
00102 class OGDF_EXPORT GraphListBase {
00103 protected:
00104     GraphElement *m_head; 
00105     GraphElement *m_tail; 
00106 
00107 public:
00109     GraphListBase() { m_head = m_tail = 0; }
00110     // destruction
00111     ~GraphListBase() { }
00112 
00114     void pushBack(GraphElement *pX) {
00115         pX->m_next = 0;
00116         pX->m_prev = m_tail;
00117         if (m_head)
00118             m_tail = m_tail->m_next = pX;
00119         else
00120             m_tail = m_head = pX;
00121     }
00122 
00124     void insertAfter(GraphElement *pX, GraphElement *pY) {
00125         pX->m_prev = pY;
00126         GraphElement *pYnext = pX->m_next = pY->m_next;
00127         pY->m_next = pX;
00128         if (pYnext) pYnext->m_prev = pX;
00129         else m_tail = pX;
00130     }
00131 
00133     void insertBefore(GraphElement *pX, GraphElement *pY) {
00134         pX->m_next = pY;
00135         GraphElement *pYprev = pX->m_prev = pY->m_prev;
00136         pY->m_prev = pX;
00137         if (pYprev) pYprev->m_next = pX;
00138         else m_head = pX;
00139     }
00140 
00142     void del(GraphElement *pX) {
00143         GraphElement *pxPrev = pX->m_prev, *pxNext = pX->m_next;
00144 
00145         if (pxPrev)
00146             pxPrev->m_next = pxNext;
00147         else
00148             m_head = pxNext;
00149         if (pxNext)
00150             pxNext->m_prev = pxPrev;
00151         else
00152             m_tail = pxPrev;
00153     }
00154 
00156     template<class LIST>
00157     void sort(const LIST &newOrder) {
00158         GraphElement *pPred = 0;
00159         typename LIST::const_iterator it = newOrder.begin();
00160         if (!it.valid()) return;
00161 
00162         m_head = *it;
00163         for(; it.valid(); ++it) {
00164             GraphElement *p = *it;
00165             if ((p->m_prev = pPred) != 0) pPred->m_next = p;
00166             pPred = p;
00167         }
00168 
00169         (m_tail = pPred)->m_next = 0;
00170     }
00171 
00173     void reverse() {
00174         GraphElement *pX = m_head;
00175         m_head = m_tail;
00176         m_tail = pX;
00177         while(pX) {
00178             GraphElement *pY = pX->m_next;
00179             pX->m_next = pX->m_prev;
00180             pX = pX->m_prev = pY;
00181         }
00182     }
00183 
00185     void swap(GraphElement *pX, GraphElement *pY) {
00186         if (pX->m_next == pY) {
00187             pX->m_next = pY->m_next;
00188             pY->m_prev = pX->m_prev;
00189             pY->m_next = pX;
00190             pX->m_prev = pY;
00191 
00192         } else if(pY->m_next == pX) {
00193             pY->m_next = pX->m_next;
00194             pX->m_prev = pY->m_prev;
00195             pX->m_next = pY;
00196             pY->m_prev = pX;
00197 
00198         } else {
00199             swap(pX->m_next,pY->m_next);
00200             swap(pX->m_prev,pY->m_prev);
00201         }
00202 
00203         if(pX->m_prev)
00204             pX->m_prev->m_next = pX;
00205         else
00206             m_head = pX;
00207         if(pX->m_next)
00208             pX->m_next->m_prev = pX;
00209         else
00210             m_tail = pX;
00211 
00212         if(pY->m_prev)
00213             pY->m_prev->m_next = pY;
00214         else
00215             m_head = pY;
00216         if(pY->m_next)
00217             pY->m_next->m_prev = pY;
00218         else
00219             m_tail = pY;
00220 
00221         OGDF_ASSERT(consistencyCheck());
00222     }
00223 
00224 
00226     bool consistencyCheck() {
00227         if (m_head == 0) {
00228             return (m_tail == 0);
00229 
00230         } else if (m_tail == 0) {
00231             return false;
00232 
00233         } else {
00234             if (m_head->m_prev != 0)
00235                 return false;
00236             if (m_tail->m_next != 0)
00237                 return false;
00238 
00239             GraphElement *pX = m_head;
00240             for(; pX; pX = pX->m_next) {
00241                 if (pX->m_prev) {
00242                     if (pX->m_prev->m_next != pX)
00243                         return false;
00244                 } else if(pX != m_head)
00245                     return false;
00246 
00247                 if (pX->m_next) {
00248                     if (pX->m_next->m_prev != pX)
00249                         return false;
00250                 } else if (pX != m_tail)
00251                     return false;
00252             }
00253         }
00254 
00255         return true;
00256     }
00257 
00258     OGDF_NEW_DELETE
00259 }; // class GraphListBase
00260 
00261 
00263 
00266 template<class T> class GraphList : protected GraphListBase {
00267 public:
00269     GraphList() { }
00270     // destruction (deletes all elements)
00271     ~GraphList() {
00272         if (m_head)
00273             OGDF_ALLOCATOR::deallocateList(sizeof(T), m_head,m_tail);
00274     }
00275 
00277     T *begin () const { return (T *)m_head; }
00279     T *rbegin() const { return (T *)m_tail; }
00280 
00282     bool empty() { return m_head; }
00283 
00285     void pushBack(T *pX) {
00286         GraphListBase::pushBack(pX);
00287     }
00288 
00290     void insertAfter(T *pX, T *pY) {
00291         GraphListBase::insertAfter(pX,pY);
00292     }
00293 
00295     void insertBefore(T *pX, T *pY) {
00296         GraphListBase::insertBefore(pX,pY);
00297     }
00298 
00300     void move(T *pX, GraphList<T> &L, T *pY, Direction dir) {
00301         GraphListBase::del(pX);
00302         if (dir == after)
00303             L.insertAfter(pX,pY);
00304         else
00305             L.insertBefore(pX,pY);
00306     }
00307 
00309     void move(T *pX, GraphList<T> &L) {
00310         GraphListBase::del(pX);
00311         L.pushBack(pX);
00312     }
00313 
00315     void moveAfter(T *pX, T *pY){
00316         GraphListBase::del(pX);
00317         insertAfter(pX,pY);
00318     }
00319 
00321     void moveBefore(T *pX, T *pY){
00322         GraphListBase::del(pX);
00323         insertBefore(pX,pY);
00324     }
00325 
00327     void del(T *pX) {
00328         GraphListBase::del(pX);
00329         delete pX;
00330     }
00331 
00333     void delPure(T *pX) {
00334         GraphListBase::del(pX);
00335     }
00336 
00338     void clear() {
00339         if (m_head) {
00340             OGDF_ALLOCATOR::deallocateList(sizeof(T),m_head,m_tail);
00341             m_head = m_tail = 0;
00342         }
00343     }
00344 
00346     template<class T_LIST>
00347     void sort(const T_LIST &newOrder) {
00348         GraphListBase::sort(newOrder);
00349     }
00350 
00351 
00353     void reverse() {
00354         GraphListBase::reverse();
00355     }
00356 
00358     void swap(T *pX, T *pY) {
00359         GraphListBase::swap(pX,pY);
00360     }
00361 
00362 
00364     bool consistencyCheck() {
00365         return GraphListBase::consistencyCheck();
00366     }
00367     
00368     
00369     OGDF_NEW_DELETE
00370 }; // class GraphList<T>
00371 
00372 
00373 typedef NodeElement *node; 
00374 typedef EdgeElement *edge; 
00375 typedef AdjElement *adjEntry; 
00376 
00377 
00378 
00380 
00384 class OGDF_EXPORT AdjElement : private GraphElement {
00385     friend class Graph;
00386     friend class GraphListBase;
00387     friend class GraphList<AdjElement>;
00388 
00389     AdjElement *m_twin; 
00390     edge m_edge; 
00391     node m_node; 
00392     int m_id;    
00393 
00395     AdjElement(node v) : m_node(v) { }
00397     AdjElement(edge e, int id) : m_edge(e), m_id(id) { }
00398 
00399 public:
00401     edge theEdge() const { return m_edge; }
00403     operator edge() const { return m_edge; }
00405     node theNode() const { return m_node; }
00406 
00408     adjEntry twin() const { return m_twin; }
00409 
00411     node twinNode() const { return m_twin->m_node; }
00412 
00414     int index() const { return m_id; }
00415 
00416     // traversing faces in clockwise (resp. counter-clockwise) order
00417     // (if face is an interior face)
00418     
00420     adjEntry clockwiseFaceSucc() const { return m_twin->cyclicPred(); }
00422     adjEntry clockwiseFacePred() const { return cyclicSucc()->m_twin; }
00424     adjEntry counterClockwiseFaceSucc() const { return m_twin->cyclicSucc(); }
00426     adjEntry counterClockwiseFacePred() const { return cyclicPred()->m_twin; }
00427 
00428     // default is traversing faces in clockwise order
00430     adjEntry faceCycleSucc() const { return clockwiseFaceSucc(); }
00432     adjEntry faceCyclePred() const { return clockwiseFacePred(); }
00433 
00434 
00436     adjEntry succ() const { return (adjEntry)m_next; }
00438     adjEntry pred() const { return (adjEntry)m_prev; }
00439 
00441     adjEntry cyclicSucc() const;
00443     adjEntry cyclicPred() const;
00444 
00445 #ifdef OGDF_DEBUG
00446     const Graph *graphOf() const;
00447 #endif
00448 
00449     OGDF_NEW_DELETE
00450 }; // class AdjElement
00451 
00452 
00454 class OGDF_EXPORT NodeElement : private GraphElement {
00455     friend class Graph;
00456     friend class GraphList<NodeElement>;
00457 
00458     GraphList<AdjElement> m_adjEdges; 
00459     int m_indeg;  
00460     int m_outdeg; 
00461     int m_id;     
00462 
00463 #ifdef OGDF_DEBUG
00464     // we store the graph containing this node for debugging purposes
00465     const Graph *m_pGraph; 
00466 #endif
00467 
00468 
00469     // construction
00470 #ifdef OGDF_DEBUG
00471 
00472 
00477     NodeElement(const Graph *pGraph, int id) :
00478         m_indeg(0), m_outdeg(0), m_id(id), m_pGraph(pGraph) { }
00479 #else
00480     NodeElement(int id) : m_indeg(0), m_outdeg(0), m_id(id) { }
00481 #endif
00482 
00483 
00484 public:
00486     int index() const { return m_id; }
00487 
00489     int indeg() const { return m_indeg; }
00491     int outdeg() const { return m_outdeg; }
00493     int degree() const { return m_indeg + m_outdeg; }
00494 
00496     adjEntry firstAdj() const { return m_adjEdges.begin();  }
00498     adjEntry lastAdj () const { return m_adjEdges.rbegin(); }
00499 
00501     node succ() const { return (node)m_next; }
00503     node pred() const { return (node)m_prev; }
00504 
00505 #ifdef OGDF_DEBUG
00506 
00507     const Graph *graphOf() const { return m_pGraph; }
00508 #endif
00509 
00510     OGDF_NEW_DELETE
00511 }; // class NodeElement
00512 
00513 
00514 inline adjEntry AdjElement::cyclicSucc() const
00515 {
00516     return (m_next) ? (adjEntry)m_next : m_node->firstAdj();
00517 }
00518 
00519 inline adjEntry AdjElement::cyclicPred() const
00520 {
00521     return (m_prev) ? (adjEntry)m_prev : m_node->lastAdj();
00522 }
00523 
00524 inline bool test_forall_adj_edges(adjEntry &adj, edge &e)
00525 {
00526     if (adj) { e = adj->theEdge(); return true; }
00527     else return false;
00528 }
00529 
00530 
00531 
00533 class OGDF_EXPORT EdgeElement : private GraphElement {
00534     friend class Graph;
00535     friend class GraphList<EdgeElement>;
00536 
00537     node m_src; 
00538     node m_tgt; 
00539     AdjElement *m_adjSrc; 
00540     AdjElement *m_adjTgt; 
00541     int m_id; // The (unique) index of the node.
00542 
00544 
00551     EdgeElement(node src, node tgt, AdjElement *adjSrc, AdjElement *adjTgt, int id) :
00552         m_src(src), m_tgt(tgt), m_adjSrc(adjSrc), m_adjTgt(adjTgt), m_id(id) { }
00553         
00555 
00560     EdgeElement(node src, node tgt, int id) :
00561         m_src(src), m_tgt(tgt), m_id(id) { }
00562 
00563 public:
00565     int index() const { return m_id; }
00567     node source() const { return m_src; }
00569     node target() const { return m_tgt; }
00570 
00572     adjEntry adjSource() const { return m_adjSrc; }
00574     adjEntry adjTarget() const { return m_adjTgt; }
00575 
00577     node opposite(node v) const { return (v == m_src) ? m_tgt : m_src; }
00578     // Returns true iff the edge is a self-loop (source node = target node).
00579     bool isSelfLoop() const { return m_src == m_tgt; }
00580 
00582     edge succ() const { return (edge)m_next; }
00584     edge pred() const { return (edge)m_prev; }
00585 
00586 #ifdef OGDF_DEBUG
00587 
00588     const Graph *graphOf() const { return m_src->graphOf(); }
00589 #endif
00590 
00592     bool isIncident(node v) const { return v == m_src || v == m_tgt; }
00593     
00595     node commonNode(edge e) const { return (m_src==e->m_src || m_src==e->m_tgt) ? m_src : ((m_tgt==e->m_src || m_tgt==e->m_tgt) ? m_tgt: 0); }
00596 
00597     OGDF_NEW_DELETE
00598 }; // class EdgeElement
00599 
00600 
00601 #ifdef OGDF_DEBUG
00602 inline const Graph *AdjElement::graphOf() const {
00603     return m_node->graphOf();
00604 }
00605 #endif
00606 
00607 
00608 template<>inline bool doDestruction<node>(const node *) { return false; }
00609 template<>inline bool doDestruction<edge>(const edge *) { return false; }
00610 template<>inline bool doDestruction<adjEntry>(const adjEntry *) { return false; }
00611 
00612 class NodeArrayBase;
00613 class EdgeArrayBase;
00614 class AdjEntryArrayBase;
00615 template<class T> class NodeArray;
00616 template<class T> class EdgeArray;
00617 template<class T> class AdjEntryArray;
00618 class OGDF_EXPORT GraphObserver;
00619 
00620 
00621 //---------------------------------------------------------
00622 // iteration macros
00623 //---------------------------------------------------------
00624 
00626 #define forall_nodes(v,G) for((v)=(G).firstNode(); (v); (v)=(v)->succ())
00627 
00628 #define forall_rev_nodes(v,G) for((v)=(G).lastNode(); (v); (v)=(v)->pred())
00629 
00631 #define forall_edges(e,G) for((e)=(G).firstEdge(); (e); (e)=(e)->succ())
00632 
00633 #define forall_rev_edges(e,G) for((e)=(G).lastEdge(); (e); (e)=(e)->pred())
00634 
00636 #define forall_adj(adj,v) for((adj)=(v)->firstAdj(); (adj); (adj)=(adj)->succ())
00637 
00638 #define forall_rev_adj(adj,v) for((adj)=(v)->lastAdj(); (adj); (adj)=(adj)->pred())
00639 
00641 #define forall_adj_edges(e,v)\
00642 for(ogdf::adjEntry ogdf_loop_var=(v)->firstAdj();\
00643     ogdf::test_forall_adj_edges(ogdf_loop_var,(e));\
00644     ogdf_loop_var=ogdf_loop_var->succ())
00645 
00646 
00648 
00699 class OGDF_EXPORT Graph
00700 {
00701     GraphList<NodeElement> m_nodes; 
00702     GraphList<EdgeElement> m_edges; 
00703     int m_nNodes; 
00704     int m_nEdges; 
00705 
00706     int m_nodeIdCount; 
00707     int m_edgeIdCount; 
00708 
00709     int m_nodeArrayTableSize; 
00710     int m_edgeArrayTableSize; 
00711 
00712     mutable ListPure<NodeArrayBase*> m_regNodeArrays; 
00713     mutable ListPure<EdgeArrayBase*> m_regEdgeArrays; 
00714     mutable ListPure<AdjEntryArrayBase*> m_regAdjArrays;  
00715     mutable ListPure<GraphObserver*> m_regStructures; 
00716 
00717     GraphList<EdgeElement> m_hiddenEdges; 
00718 
00719 public:
00720     //
00721     // enumerations
00722     //
00723 
00725     enum EdgeType {
00726         association = 0,
00727         generalization = 1,
00728         dependency = 2
00729     }; // should be more flexible, standard, dissect, expand
00730     
00732     enum NodeType {
00733         vertex,
00734         dummy,
00735         generalizationMerger,
00736         generalizationExpander,
00737         highDegreeExpander,
00738         lowDegreeExpander,
00739         associationClass
00740     };
00741 
00742 
00744     Graph();
00745     
00747 
00752     Graph(const Graph &G);
00753     
00754     // destruction
00755     virtual ~Graph();
00756 
00757 
00762 
00764     bool empty() const { return m_nNodes == 0; }
00765 
00767     int numberOfNodes() const { return m_nNodes; }
00768 
00770     int numberOfEdges() const { return m_nEdges; }
00771 
00773     int maxNodeIndex() const { return m_nodeIdCount-1; }
00775     int maxEdgeIndex() const { return m_edgeIdCount-1; }
00777     int maxAdjEntryIndex() const { return (m_edgeIdCount<<1)-1; }
00778 
00780     int nodeArrayTableSize() const { return m_nodeArrayTableSize; }
00782     int edgeArrayTableSize() const { return m_edgeArrayTableSize; }
00784     int adjEntryArrayTableSize() const { return m_edgeArrayTableSize << 1; }
00785 
00787     node firstNode() const { return m_nodes.begin (); }
00789     node lastNode () const { return m_nodes.rbegin(); }
00790     
00792     edge firstEdge() const { return m_edges.begin (); }
00794     edge lastEdge () const { return m_edges.rbegin(); }
00795 
00797     node chooseNode() const;
00799     edge chooseEdge() const;
00800 
00802     template<class NODELIST>
00803     void allNodes(NODELIST &nodes) const {
00804         nodes.clear();
00805         for (node v = m_nodes.begin(); v; v = v->succ())
00806             nodes.pushBack(v);
00807     }
00808 
00810     template<class EDGELIST>
00811     void allEdges(EDGELIST &edges) const {
00812         edges.clear();
00813         for (edge e = m_edges.begin(); e; e = e->succ())
00814             edges.pushBack(e);
00815     }
00816 
00818     template<class EDGELIST>
00819     void adjEdges(node v, EDGELIST &edges) const {
00820         edges.clear();
00821         edge e;
00822         forall_adj_edges(e,v)
00823             edges.pushBack(e);
00824     }
00825 
00827     template<class ADJLIST>
00828     void adjEntries(node v, ADJLIST &entries) const {
00829         entries.clear();
00830         adjEntry adj;
00831         forall_adj(adj,v)
00832             entries.pushBack(adj);
00833     }
00834 
00836     template<class EDGELIST>
00837     void inEdges(node v, EDGELIST &edges) const {
00838         edges.clear();
00839         edge e;
00840         forall_adj_edges(e,v)
00841             if (e->target() == v) edges.pushBack(e);
00842     }
00843 
00845     template<class EDGELIST>
00846     void outEdges(node v, EDGELIST &edges) const {
00847         edges.clear();
00848         edge e;
00849         forall_adj_edges(e,v)
00850             if (e->source() == v) edges.pushBack(e);
00851     }
00852 
00853 
00855 
00859 
00861     node newNode();
00862 
00864 
00871     node newNode(int index);
00872 
00874     edge newEdge(node v, node w);
00875 
00877 
00884     edge newEdge(node v, node w, int index);
00885 
00887 
00899     edge newEdge(adjEntry adjSrc, adjEntry adjTgt, Direction dir = ogdf::after);
00900     
00902 
00910     edge newEdge(node v, adjEntry adjTgt);
00911 
00913 
00921     edge newEdge(adjEntry adjSrc, node w);
00922 
00923 
00925 
00929 
00931     void delNode(node v);
00932 
00934     void delEdge(edge e);
00935 
00937     void clear();
00938 
00939     
00941 
00949 
00951 
00956     void hideEdge(edge e);
00957 
00959 
00962     void restoreEdge(edge e);
00963 
00965     void restoreAllEdges();
00966 
00971 
00972     
00974 
00980     virtual edge split(edge e);
00981 
00983 
00990     void unsplit(node u);
00991 
00993 
01001     virtual void unsplit(edge eIn, edge eOut);
01002 
01004 
01021     node splitNode(adjEntry adjStartLeft, adjEntry adjStartRight);
01022 
01024     node contract(edge e);
01025 
01026     // moves edge e to adjacency list of owner(adjSrc) inserting it before
01027     // or after adjSrc, and to owner(adjTgt) inserting it before or after
01028     // adjTgt; e is afterwards an edge from owner(adjSrc) to owner(adjTgt)
01029     void move(edge e, adjEntry adjSrc, Direction dirSrc,
01030         adjEntry adjTgt, Direction dirTgt);
01031 
01033 
01036     void moveTarget(edge e, node w);
01037 
01039 
01043     void moveTarget(edge e, adjEntry adjTgt, Direction dir);
01044 
01046 
01049     void moveSource(edge e, node w);
01050 
01052 
01056     void moveSource(edge e, adjEntry adjSrc, Direction dir);
01057     
01059     //  If no such edge exists, 0 is returned.
01060     edge searchEdge (node v, node w) const;
01061 
01063     void reverseEdge(edge e);
01064 
01066     void reverseAllEdges();
01067 
01069 
01072     template<class NODELIST>
01073     void collaps(NODELIST &nodes){
01074         node v = nodes.popFrontRet();
01075         while (!nodes.empty())
01076         {
01077             node w = nodes.popFrontRet();
01078             adjEntry adj = w->firstAdj();
01079             while (adj !=0)
01080             {
01081                 adjEntry succ = adj->succ();
01082                 edge e = adj->theEdge();
01083                 if (e->source() == v || e->target() == v)
01084                     delEdge(e);
01085                 else if (e->source() == w)
01086                     moveSource(e,v);
01087                 else
01088                     moveTarget(e,v);
01089                 adj = succ;
01090             }
01091             delNode(w);
01092         }
01093     }
01094 
01096 
01099     template<class ADJ_ENTRY_LIST>
01100     void sort(node v, const ADJ_ENTRY_LIST &newOrder) {
01101 #ifdef OGDF_DEBUG
01102         typename ADJ_ENTRY_LIST::const_iterator it;
01103         for(it = newOrder.begin(); it.valid() ; ++it) {
01104             OGDF_ASSERT((*it)->theNode() == v);
01105         }
01106 #endif
01107         v->m_adjEdges.sort(newOrder);
01108     }
01109 
01111     void reverseAdjEdges(node v) {
01112         v->m_adjEdges.reverse();
01113     }
01114 
01116 
01122     void moveAdj(adjEntry adjMove, Direction dir, adjEntry adjPos) {
01123         OGDF_ASSERT(adjMove->graphOf() == this && adjPos->graphOf() == this);
01124         OGDF_ASSERT(adjMove != 0 && adjPos != 0);
01125         GraphList<AdjElement> &adjList = adjMove->m_node->m_adjEdges;
01126         adjList.move(adjMove, adjList, adjPos, dir);
01127     }
01128 
01130 
01135     void moveAdjAfter(adjEntry adjMove, adjEntry adjAfter) {
01136         OGDF_ASSERT(adjMove->graphOf() == this && adjAfter->graphOf() == this);
01137         OGDF_ASSERT(adjMove != 0 && adjAfter != 0);
01138         adjMove->m_node->m_adjEdges.moveAfter(adjMove,adjAfter);
01139     }
01140 
01142 
01147     void moveAdjBefore(adjEntry adjMove, adjEntry adjBefore) {
01148         OGDF_ASSERT(adjMove->graphOf() == this && adjBefore->graphOf() == this);
01149         OGDF_ASSERT(adjMove != 0 && adjBefore != 0);
01150         adjMove->m_node->m_adjEdges.moveBefore(adjMove,adjBefore);
01151     }
01152 
01154     void reverseAdjEdges();
01155 
01157 
01160     void swapAdjEdges(adjEntry adj1, adjEntry adj2) {
01161         OGDF_ASSERT(adj1->theNode() == adj2->theNode());
01162         OGDF_ASSERT(adj1->graphOf() == this);
01163 
01164         adj1->theNode()->m_adjEdges.swap(adj1,adj2);
01165     }
01166 
01167 
01169 
01173 
01175     bool readGML(const char *fileName);
01176 
01178     bool readGML(istream &is);
01179 
01181     void writeGML(const char *fileName) const;
01182 
01184     void writeGML(ostream &os) const;
01185 
01187     bool readLEDAGraph(const char *fileName);
01188 
01190     bool readLEDAGraph(istream &is);
01191 
01192 
01194 
01198 
01200 
01208     int genus() const;
01209 
01211     bool representsCombEmbedding() const {
01212         return (genus() == 0);
01213     }
01214 
01216 
01219     bool consistencyCheck() const;
01220 
01221 
01223 
01229 
01231     ListIterator<NodeArrayBase*> registerArray(NodeArrayBase *pNodeArray) const;
01233     ListIterator<EdgeArrayBase*> registerArray(EdgeArrayBase *pEdgeArray) const;
01235     ListIterator<AdjEntryArrayBase*> registerArray(AdjEntryArrayBase *pAdjArray) const;
01237     ListIterator<GraphObserver*> registerStructure(GraphObserver *pStructure) const;
01238 
01240     void unregisterArray(ListIterator<NodeArrayBase*> it) const;
01242     void unregisterArray(ListIterator<EdgeArrayBase*> it) const;
01244     void unregisterArray(ListIterator<AdjEntryArrayBase*> it) const;
01246     void unregisterStructure(ListIterator<GraphObserver*> it) const;
01247 
01248 
01250 
01274     void resetEdgeIdCount(int maxId);
01275 
01276 
01278 
01282 
01283 
01288     Graph &operator=(const Graph &G);
01289 
01290     OGDF_MALLOC_NEW_DELETE
01291 
01293 
01294 public:
01295 
01297     static int nextPower2(int start, int idCount);
01298 
01299 
01300 protected:
01301     void construct(const Graph &G, NodeArray<node> &mapNode,
01302         EdgeArray<edge> &mapEdge);
01303 
01304     void assign(const Graph &G, NodeArray<node> &mapNode,
01305         EdgeArray<edge> &mapEdge);
01306 
01313     void constructInitByNodes(
01314         const Graph &G,
01315         const List<node> &nodes,
01316         NodeArray<node> &mapNode,
01317         EdgeArray<edge> &mapEdge);
01318 
01319     void constructInitByActiveNodes(
01320         const List<node> &nodes,
01321         const NodeArray<bool> &activeNodes,
01322         NodeArray<node> &mapNode,
01323         EdgeArray<edge> &mapEdge);
01324 
01325 private:
01326     void copy(const Graph &G, NodeArray<node> &mapNode,
01327         EdgeArray<edge> &mapEdge);
01328     void copy(const Graph &G);
01329 
01330     edge createEdgeElement(node v, node w, adjEntry adjSrc, adjEntry adjTgt);
01331     node pureNewNode();
01332 
01333     // moves adjacency entry to node w
01334     void moveAdj(adjEntry adj, node w);
01335 
01336     void reinitArrays();
01337     void reinitStructures();
01338     void resetAdjEntryIndex(int newIndex, int oldIndex);
01339 
01340     bool readToEndOfLine(istream &is);
01341 }; // class Graph
01342 
01343 
01344 
01346 class OGDF_EXPORT BucketSourceIndex : public BucketFunc<edge> {
01347 public:
01349     int getBucket(const edge &e) { return e->source()->index(); }
01350 };
01351 
01353 class OGDF_EXPORT BucketTargetIndex : public BucketFunc<edge> {
01354 public:
01356     int getBucket(const edge &e) { return e->target()->index(); }
01357 };
01358 
01359 
01360 } //namespace 
01361 
01362 #endif
01363