Open
Graph Drawing
Framework

 v. 2023.09 (Elderberry)
 

Loading...
Searching...
No Matches
simple_graph_alg.h
Go to the documentation of this file.
1
32#pragma once
33
34#include <ogdf/basic/Array.h>
36#include <ogdf/basic/Graph.h>
38#include <ogdf/basic/List.h>
39#include <ogdf/basic/SList.h>
40#include <ogdf/basic/basic.h>
43#include <ogdf/basic/tuples.h>
44
45#include <functional>
46
47namespace ogdf {
48
51
58
60
67
69
76template<class NODELIST>
77void makeLoopFree(Graph& G, NODELIST& L) {
78 L.clear();
79
80 safeForEach(G.edges, [&](edge e) {
81 if (e->isSelfLoop()) {
82 L.pushBack(e->source());
83 G.delEdge(e);
84 }
85 });
86}
87
91
93
99
100
104
106
113
114
116
127
129
142template<bool ONLY_ONCE = false>
143int numParallelEdges(const Graph& G) {
144 if (G.numberOfEdges() <= 1) {
145 return 0;
146 }
147
148 SListPure<edge> edges;
149 parallelFreeSort(G, edges);
150
151 int num = 0;
152 SListConstIterator<edge> it = edges.begin();
153 edge ePrev = *it, e;
154 for (it = ++it; it.valid(); ++it, ePrev = e) {
155 e = *it;
156 if (ePrev->isParallelDirected(e)) {
157 ++num;
158 if (ONLY_ONCE) {
159 return num;
160 }
161 }
162 }
163
164 return num;
165}
166
168
180template<class EDGELIST>
181void makeParallelFree(Graph& G, EDGELIST& parallelEdges) {
182 parallelEdges.clear();
183 if (G.numberOfEdges() <= 1) {
184 return;
185 }
186
187 SListPure<edge> edges;
188 parallelFreeSort(G, edges);
189
190 SListConstIterator<edge> it = edges.begin();
191 edge ePrev = *it++, e;
192 bool bAppend = true;
193 while (it.valid()) {
194 e = *it++;
195 if (e->isParallelDirected(ePrev)) {
196 G.delEdge(e);
197 if (bAppend) {
198 parallelEdges.pushBack(ePrev);
199 bAppend = false;
200 }
201 } else {
202 ePrev = e;
203 bAppend = true;
204 }
205 }
206}
207
209
218inline void makeParallelFree(Graph& G) {
219 List<edge> parallelEdges;
220 makeParallelFree(G, parallelEdges);
221}
222
224
236 EdgeArray<int>& minIndex, EdgeArray<int>& maxIndex);
237
238
240
250
252
264template<bool ONLY_ONCE = false>
266 if (G.numberOfEdges() <= 1) {
267 return 0;
268 }
269
270 SListPure<edge> edges;
271 EdgeArray<int> minIndex(G), maxIndex(G);
272 parallelFreeSortUndirected(G, edges, minIndex, maxIndex);
273
274 int num = 0;
275 SListConstIterator<edge> it = edges.begin();
276 edge ePrev = *it, e;
277 for (it = ++it; it.valid(); ++it, ePrev = e) {
278 e = *it;
279 if (minIndex[ePrev] == minIndex[e] && maxIndex[ePrev] == maxIndex[e]) {
280 ++num;
281 if (ONLY_ONCE) {
282 return num;
283 }
284 }
285 }
286
287 return num;
288}
289
291
302template<class EDGELIST>
304 if (G.numberOfEdges() <= 1) {
305 return;
306 }
307
308 SListPure<edge> edges;
309 EdgeArray<int> minIndex(G), maxIndex(G);
310 parallelFreeSortUndirected(G, edges, minIndex, maxIndex);
311
312 SListConstIterator<edge> it = edges.begin();
313 edge ePrev = *it++, e;
314 while (it.valid()) {
315 e = *it++;
316 if (minIndex[ePrev] == minIndex[e] && maxIndex[ePrev] == maxIndex[e]) {
317 parallelEdges[ePrev].pushBack(e);
318 } else {
319 ePrev = e;
320 }
321 }
322}
323
325
342template<class EDGELIST = SListPure<edge>>
343void makeParallelFreeUndirected(Graph& G, EDGELIST* parallelEdges = nullptr,
344 EdgeArray<int>* cardPositive = nullptr, EdgeArray<int>* cardNegative = nullptr) {
345 if (parallelEdges != nullptr) {
346 parallelEdges->clear();
347 }
348 if (cardPositive != nullptr) {
349 cardPositive->fill(0);
350 }
351 if (cardNegative != nullptr) {
352 cardNegative->fill(0);
353 }
354
355 if (G.numberOfEdges() <= 1) {
356 return;
357 }
358
359 EdgeArray<SListPure<edge>> parEdges(G);
360 getParallelFreeUndirected(G, parEdges);
361
362 for (edge e : G.edges) {
363 for (edge parEdge : parEdges(e)) {
364 if (cardPositive != nullptr && e->source() == parEdge->source()) {
365 (*cardPositive)[e]++;
366 }
367 if (cardNegative != nullptr && e->source() == parEdge->target()) {
368 (*cardNegative)[e]++;
369 }
370 G.delEdge(parEdge);
371 if (parallelEdges != nullptr) {
372 parallelEdges->pushBack(e);
373 }
374 }
375 }
376}
377
378template<class EDGELIST>
379OGDF_DEPRECATED("The pointer-based makeParallelFreeUndirected() should be used instead.")
380void makeParallelFreeUndirected(Graph& G, EDGELIST& parallelEdges) {
381 makeParallelFreeUndirected(G, &parallelEdges);
382}
383
384template<class EDGELIST>
385OGDF_DEPRECATED("The pointer-based makeParallelFreeUndirected() should be used instead.")
386void makeParallelFreeUndirected(Graph& G, EDGELIST& parallelEdges, EdgeArray<int>& cardPositive,
387 EdgeArray<int>& cardNegative) {
388 makeParallelFreeUndirected(G, &parallelEdges, &cardPositive, &cardNegative);
389}
390
394
396
402inline bool isSimple(const Graph& G) { return isLoopFree(G) && isParallelFree(G); }
403
405
410inline void makeSimple(Graph& G) {
411 makeLoopFree(G);
413}
414
416
423inline bool isSimpleUndirected(const Graph& G) {
424 return isLoopFree(G) && isParallelFreeUndirected(G);
425}
426
428
437
441
443
450
451
453
460
462
467inline void makeConnected(Graph& G) {
468 List<edge> added;
469 makeConnected(G, added);
470}
471
474
488 List<node>* isolated = nullptr, ArrayBuffer<node>* reprs = nullptr);
489
491
497inline int connectedComponents(const Graph& G) {
498 NodeArray<int> component(G);
499 return connectedComponents(G, component);
500}
501
502
503OGDF_DEPRECATED("connectedComponents() should be used instead.")
504
505
508inline int connectedIsolatedComponents(const Graph& G, List<node>& isolated,
509 NodeArray<int>& component) {
510 return connectedComponents(G, component, &isolated);
511}
512
519 ArrayBuffer<Tuple2<node, node>>& addEdges, bool onlyOne = false);
520
523
534inline bool findCutVertices(const Graph& G, ArrayBuffer<node>& cutVertices, bool onlyOne = false) {
536 return findCutVertices(G, cutVertices, addEdges, onlyOne);
537}
538
540
547OGDF_EXPORT bool isBiconnected(const Graph& G, node& cutVertex);
548
550
555inline bool isBiconnected(const Graph& G) {
556 node cutVertex;
557 return isBiconnected(G, cutVertex);
558}
559
561
568
570
575inline void makeBiconnected(Graph& G) {
576 List<edge> added;
577 makeBiconnected(G, added);
578}
579
587 int& nonEmptyComponents);
588
590
603inline int biconnectedComponents(const Graph& G, EdgeArray<int>& component) {
604 int doNotNeedTheValue;
605 return biconnectedComponents(G, component, doNotNeedTheValue);
606}
607
613OGDF_EXPORT bool isTwoEdgeConnected(const Graph& graph, edge& bridge);
614
628inline bool isTwoEdgeConnected(const Graph& graph) {
629 edge bridge;
630 return isTwoEdgeConnected(graph, bridge);
631}
632
634
647OGDF_EXPORT bool isTriconnected(const Graph& G, node& s1, node& s2);
648
650
656inline bool isTriconnected(const Graph& G) {
657 node s1, s2;
658 return isTriconnected(G, s1, s2);
659}
660
662
679
681
690inline bool isTriconnectedPrimitive(const Graph& G) {
691 node s1, s2;
692 return isTriconnectedPrimitive(G, s1, s2);
693}
694
696
707
708
712
714
721OGDF_EXPORT bool isAcyclic(const Graph& G, List<edge>& backedges);
722
724
730inline bool isAcyclic(const Graph& G) {
731 List<edge> backedges;
732 return isAcyclic(G, backedges);
733}
734
736
744
746
752inline bool isAcyclicUndirected(const Graph& G) {
753 List<edge> backedges;
754 return isAcyclicUndirected(G, backedges);
755}
756
758
766
767
769
777
778
780
787OGDF_EXPORT bool hasSingleSource(const Graph& G, node& source);
788
790
796inline bool hasSingleSource(const Graph& G) {
797 node source;
798 return hasSingleSource(G, source);
799}
800
802
809OGDF_EXPORT bool hasSingleSink(const Graph& G, node& sink);
810
812
818inline bool hasSingleSink(const Graph& G) {
819 node sink;
820 return hasSingleSink(G, sink);
821}
822
824
836OGDF_EXPORT bool isStGraph(const Graph& G, node& s, node& t, edge& st);
837
839
847inline bool isStGraph(const Graph& G) {
848 node s, t;
849 edge st;
850 return isStGraph(G, s, t, st);
851}
852
854
863
864
866
876
877
879
889
891
898inline void makeBimodal(Graph& G) {
899 List<edge> dummy;
900 makeBimodal(G, dummy);
901}
902
903
907
908OGDF_DEPRECATED("isAcyclicUndirected() should be used instead.")
909
910
913inline bool isFreeForest(const Graph& G) { return isAcyclicUndirected(G); }
914
916
922inline bool isTree(const Graph& G) {
923 return G.empty() || ((G.numberOfNodes() == G.numberOfEdges() + 1) && isConnected(G));
924}
925
927
939
941
950inline bool isArborescenceForest(const Graph& G) {
951 List<node> roots;
952 return isArborescenceForest(G, roots);
953}
954
955
956OGDF_DEPRECATED("isArborescenceForest() should be used instead.")
957
958
961inline bool isForest(const Graph& G, List<node>& roots) { return isArborescenceForest(G, roots); }
962
963
964OGDF_DEPRECATED("isArborescenceForest() should be used instead.")
965
966
969inline bool isForest(const Graph& G) { return isArborescenceForest(G); }
970
972
982OGDF_EXPORT bool isArborescence(const Graph& G, node& root);
983
985
994inline bool isArborescence(const Graph& G) {
995 node root;
996 return isArborescence(G, root);
997}
998
1000
1002
1009
1010
1012
1019OGDF_EXPORT bool isRegular(const Graph& G, int d);
1020
1021
1023
1032
1034
1040inline bool isBipartite(const Graph& G) {
1041 NodeArray<bool> color(G);
1042 return isBipartite(G, color);
1043}
1044
1077OGDF_EXPORT void nodeDistribution(const Graph& G, Array<int>& degdist, std::function<int(node)> func);
1078
1086inline void degreeDistribution(const Graph& G, Array<int>& degdist) {
1087 nodeDistribution(G, degdist, [](node v) { return v->degree(); });
1088}
1089
1090}
Declaration and implementation of Array class and Array algorithms.
Declaration and implementation of ArrayBuffer class.
Includes declaration of graph class.
Decralation of GraphElement and GraphList classes.
Declaration of doubly linked lists and iterators.
Declaration of singly linked lists and iterators.
Basic declarations, included by all source files.
An array that keeps track of the number of inserted elements; also usable as an efficient stack.
Definition ArrayBuffer.h:64
The parameterized class Array implements dynamic arrays of type E.
Definition Array.h:219
Class for the representation of edges.
Definition Graph_d.h:364
bool isParallelDirected(edge e) const
Returns true iff edge e is parallel to this (directed) edge (or if it is the same edge)
Definition Graph_d.h:426
Data type for general directed graphs (adjacency list representation).
Definition Graph_d.h:866
Doubly linked lists (maintaining the length of the list).
Definition List.h:1451
Class for the representation of nodes.
Definition Graph_d.h:241
int degree() const
Returns the degree of the node (indegree + outdegree).
Definition Graph_d.h:284
Encapsulates a pointer to an ogdf::SList element.
Definition SList.h:104
bool valid() const
Returns true iff the iterator points to an element.
Definition SList.h:134
Singly linked lists.
Definition SList.h:191
iterator begin()
Returns an iterator to the first element of the list.
Definition SList.h:344
Tuples of two elements (2-tuples).
Definition tuples.h:49
RegisteredArray for edges of a graph, specialized for EdgeArray<edge>.
Definition Graph_d.h:717
RegisteredArray for nodes, edges and adjEntries of a graph.
Definition Graph_d.h:659
#define OGDF_EXPORT
Specifies that a function or class is exported by the OGDF dynamic library (shared object / DLL),...
Definition config.h:117
Decralation of graph iterators.
int connectedComponents(const Graph &G, NodeArray< int > &component, List< node > *isolated=nullptr, ArrayBuffer< node > *reprs=nullptr)
Computes the connected components of G and optionally generates a list of isolated nodes.
bool isBiconnected(const Graph &G, node &cutVertex)
Returns true iff G is biconnected.
void makeBiconnected(Graph &G, List< edge > &added)
Makes G biconnected by adding edges.
void makeConnected(Graph &G, List< edge > &added)
Makes G connected by adding a minimum number of edges.
int biconnectedComponents(const Graph &G, EdgeArray< int > &component, int &nonEmptyComponents)
Computes the biconnected components of G.
bool isConnected(const Graph &G)
Returns true iff G is connected.
bool isTwoEdgeConnected(const Graph &graph, edge &bridge)
Returns true iff graph is 2-edge-connected.
bool isTriconnected(const Graph &G, node &s1, node &s2)
Returns true iff G is triconnected.
bool findCutVertices(const Graph &G, ArrayBuffer< node > &cutVertices, ArrayBuffer< Tuple2< node, node > > &addEdges, bool onlyOne=false)
Finds cut vertices and potential edges that could be added to turn the cut vertices into non-cut vert...
void triangulate(Graph &G)
Triangulates a planarly embedded graph G by adding edges.
bool isTriconnectedPrimitive(const Graph &G, node &s1, node &s2)
Returns true iff G is triconnected (using a quadratic time algorithm!).
bool isAcyclic(const Graph &G, List< edge > &backedges)
Returns true iff the digraph G is acyclic.
int strongComponents(const Graph &G, NodeArray< int > &component)
Computes the strongly connected components of the digraph G.
void makeAcyclicByReverse(Graph &G)
Makes the digraph G acyclic by reversing edges.
void makeBimodal(Graph &G, List< edge > &newEdges)
Makes the digraph G bimodal.
bool hasSingleSource(const Graph &G, node &source)
Returns true iff the digraph G contains exactly one source node (or is empty).
bool isStGraph(const Graph &G, node &s, node &t, edge &st)
Returns true iff G is an st-digraph.
bool hasSingleSink(const Graph &G, node &sink)
Returns true iff the digraph G contains exactly one sink node (or is empty).
void makeAcyclic(Graph &G)
Makes the digraph G acyclic by removing edges.
void topologicalNumbering(const Graph &G, NodeArray< int > &num)
Computes a topological numbering of an acyclic digraph G.
bool isAcyclicUndirected(const Graph &G, List< edge > &backedges)
Returns true iff the undirected graph G is acyclic.
bool isParallelFreeUndirected(const Graph &G)
Returns true iff G contains no undirected parallel edges.
void makeLoopFree(Graph &G, NODELIST &L)
Removes all self-loops from G and returns all nodes with self-loops in L.
bool isParallelFree(const Graph &G)
Returns true iff G contains no parallel edges.
void makeSimple(Graph &G)
Removes all self-loops and all but one edge of each bundle of parallel edges.
void makeParallelFreeUndirected(Graph &G, EDGELIST *parallelEdges=nullptr, EdgeArray< int > *cardPositive=nullptr, EdgeArray< int > *cardNegative=nullptr)
Removes all but one edge of each bundle of undirected parallel edges.
bool isLoopFree(const Graph &G)
Returns true iff G contains no self-loop.
void parallelFreeSort(const Graph &G, SListPure< edge > &edges)
Sorts the edges of G such that parallel edges come after each other in the list.
void parallelFreeSortUndirected(const Graph &G, SListPure< edge > &edges, EdgeArray< int > &minIndex, EdgeArray< int > &maxIndex)
Sorts the edges of G such that undirected parallel edges come after each other in the list.
int numParallelEdgesUndirected(const Graph &G)
Returns the number of undirected parallel edges in G.
void makeParallelFree(Graph &G, EDGELIST &parallelEdges)
Removes all but one of each bundle of parallel edges.
void removeSelfLoops(Graph &graph, node v)
Removes all self-loops for a given node v in graph.
void getParallelFreeUndirected(const Graph &G, EdgeArray< EDGELIST > &parallelEdges)
Computes the bundles of undirected parallel edges in G.
bool isSimpleUndirected(const Graph &G)
Returns true iff G contains neither self-loops nor undirected parallel edges.
bool isSimple(const Graph &G)
Returns true iff G contains neither self-loops nor parallel edges.
bool hasNonSelfLoopEdges(const Graph &G)
Returns whether G has edges which are not self-loops.
int numParallelEdges(const Graph &G)
Returns the number of parallel edges in G.
void makeSimpleUndirected(Graph &G)
Removes all self-loops and all but one edge of each bundle of undirected parallel edges.
bool isArborescenceForest(const Graph &G, List< node > &roots)
Returns true iff G is a forest consisting only of arborescences.
bool isArborescence(const Graph &G, node &root)
Returns true iff G represents an arborescence.
bool isTree(const Graph &G)
Returns true iff G is a tree, i.e. contains no undirected cycle and is connected.
bool isBipartite(const Graph &G, NodeArray< bool > &color)
Checks whether a graph is bipartite.
void degreeDistribution(const Graph &G, Array< int > &degdist)
Fills degdist with the degree distribution of graph G.
void nodeDistribution(const Graph &G, Array< int > &degdist, std::function< int(node)> func)
Fills dist with the distribution given by a function func in graph G.
bool isRegular(const Graph &G)
Checks if a graph is regular.
#define OGDF_DEPRECATED(reason)
Mark a class / member / function as deprecated.
Definition config.h:206
Implementation of algorithms as templates working with different list types.
The namespace for all OGDF objects.
void safeForEach(CONTAINER &container, std::function< void(typename CONTAINER::value_type)> func)
Calls (possibly destructive) func for each element of container.
Declaration and implementation of class Tuple2, Tuple3 and Tuple4.