-
Notifications
You must be signed in to change notification settings - Fork 3
/
Copy pathTopological.h
117 lines (108 loc) · 3.9 KB
/
Topological.h
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
#ifndef CH4_TOPOLOGICAL_H
#define CH4_TOPOLOGICAL_H
#include "../head/Digraph.h"
#include "../head/DirectedCycle.h"
#include "../head/EdgeWeightedDigraph.h"
#include "../head/EdgeWeightedDirectedCycle.h"
#include "../head/DepthFirstOrder.h"
/**
* The {@code Topological} class represents a data type for
* determining a topological order of a directed acyclic graph (DAG).
* Recall, a digraph has a topological order if and only if it is a DAG.
* The <em>hasOrder</em> operation determines whether the digraph has
* a topological order, and if so, the <em>order</em> operation
* returns one.
* <p>
* This implementation uses depth-first search.
* The constructor takes time proportional to <em>V</em> + <em>E</em>
* (in the worst case),
* where <em>V</em> is the number of vertices and <em>E</em> is the number of edges.
* Afterwards, the <em>hasOrder</em> and <em>rank</em> operations takes constant time;
* the <em>order</em> operation takes time proportional to <em>V</em>.
* <p>
* See {@link DirectedCycle}, {@link DirectedCycleX}, and
* {@link EdgeWeightedDirectedCycle} to compute a
* directed cycle if the digraph is not a DAG.
* See {@link TopologicalX} for a nonrecursive queue-based algorithm
* to compute a topological order of a DAG.
* <p>
* For additional documentation,
* see <a href="https://algs4.cs.princeton.edu/42digraph">Section 4.2</a> of
* <i>Algorithms, 4th Edition</i> by Robert Sedgewick and Kevin Wayne.
*
* @author Robert Sedgewick
* @author Kevin Wayne
*/
class Topological {
public:
/**
* Determines whether the digraph {@code G} has a topological order and, if so,
* finds such a topological order.
* @param G the digraph
*/
Topological(Digraph &G) : rank(G.getV()) {
DirectedCycle finder(G);
if (!finder.hasCycle()) {
DepthFirstOrder dfs(G);
order = dfs.reversePost();
int i = 0;
for (int v : order)
rank[v] = i++;
}
}
/**
* Determines whether the edge-weighted digraph {@code G} has a topological
* order and, if so, finds such an order.
* @param G the edge-weighted digraph
*/
Topological(EdgeWeightedDigraph &G) {
EdgeWeightedDirectedCycle finder(G);
if (!finder.hasCycle()) {
DepthFirstOrder dfs(G);
order = dfs.reversePost();
}
}
/**
* Returns a topological order if the digraph has a topologial order,
* and {@code null} otherwise.
* @return a topological order of the vertices (as an interable) if the
* digraph has a topological order (or equivalently, if the digraph is a DAG),
* and {@code null} otherwise
*/
forward_list<int> getorder() {
return order;
}
/**
* Does the digraph have a topological order?
* @return {@code true} if the digraph has a topological order (or equivalently,
* if the digraph is a DAG), and {@code false} otherwise
*/
bool hasOrder() {
return !order.empty();
}
/**
* The the rank of vertex {@code v} in the topological order;
* -1 if the digraph is not a DAG
*
* @param v the vertex
* @return the position of vertex {@code v} in a topological order
* of the digraph; -1 if the digraph is not a DAG
* @throws IllegalArgumentException unless {@code 0 <= v < V}
*/
int getrank(int v) {
validateVertex(v);
if (hasOrder()) return rank[v];
else return -1;
}
private:
// throw an IllegalArgumentException unless {@code 0 <= v < V}
void validateVertex(int v) {
int V = rank.size();
if (v < 0 || v >= V)
throw runtime_error("vertex " + to_string(v) + " is not between 0 and " + to_string(V - 1));
}
private:
forward_list<int> order; // topological order
vector<int> rank; // rank[v] = rank of vertex v in order
};
#endif //CH4_TOPOLOGICAL_H