4.2.1 术语
由一组顶点和一组有方向的边组成的,每条有方向的边都连接着有序的一对顶点
4.2.2 有向图的数据类型
public class Digraph | |
---|
Digraph(int V) | 创建一幅含有V个顶点但没有边的有向图 |
Digraph(In in) | 从输入流 in 中读取一幅有向图 |
int V() | 顶点总数 |
int E() | 边的总数 |
void addEdge(int v, int w) | 向有向图中添加一条边 v → w |
Iterable adj(int v) | 由 v 指出的边所连接的所有顶点 |
Digraph reverse() | 该图的反向图 |
String toString() | 对象的字符串表示 |
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
| public class Digraph
{
private final int V;
private int E;
private Bag<Integer>[] adj;
public Digraph(int V)
{
this.V = V;
this.E = 0;
adj = (Bag<Integer>[]) new Bag[v];
for(int v=0;v<V;v++)
adj[v] = new Bag<Integer>();
}
public int V(){return V:}
public int E(){return E;}
public void addEdge(int v,int w)
{
adj[v].add(w);
E++;
}
public Iterable<Integer> adj(int v){return adj[v];}
public Digraph reverse()
{
Digraph R = new Digraph(V);
for(int v=0;v<V;v++)
for(int w:adj(v))
R.addEdge(w,v);
return R;
}
}
|
4.2.3 有向图中的可达性
public class DirectedDFS | |
---|
DirectedDFS(Digraph G, int s) | 在 G 中找到从s可达的所有顶点 |
DirectedDFS(Digraph G,Iterable sources) | 在 G 中找到从sources中的所有顶点可达的所有顶点 |
boolean marked(int v) | v 是可达的吗 |
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
| public class DirectedDFS
{
private boolean[] marked;
public DirectedDFS(Digraph G, int s)
{
marked = new boolean[G.V()];
dfs(G, s);
}
public DirectedDFS(Digraph G, Iterable<Integer> sources)
{
marked = new boolean[G.V()];
for (int s : sources)
if (!marked[s]) dfs(G, s);
}
private void dfs(Digraph G, int v)
{
marked[v] = true;
for (int w : G.adj(v))
if (!marked[w]) dfs(G, w);
}
public boolean marked(int v) { return marked[v]; }
}
|
4.2.3.1 标记 - 清除的垃圾收集
4.2.4 环和有向无环图
4.2.4.1 调度问题
拓扑排序:给定一幅有向图,将所有的顶点排序,使得所有的有向边均从排在前面的元素指向排在后面的元素(或者说明无法做到这一点)
4.2.4.2 有向图中的环
有向环检测:给定的有向图中包含有向环吗?如果有,按照路径的方向从某个顶点并返回自己来找到环上的所有顶点
public class DirectedCycle | |
---|
DirectedCycle(Digraph G) | 寻找有向环的构造函数 |
boolean hasCycle() | G 是否含有有向环 |
Iterable cycle() | 有向环中的所有顶点(如果存在的话) |
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
| public class DirectedCycle{
private boolean[] marked;
private int[] edgeTo;
private Stack<Integer> cycle; //有向环中的所有顶点(如果存在)
private boolean[] onStack; //递归调用的栈上的所有顶点
public DirectedCycle(Digraph G){
onStack = new boolean[G.V()];
edgeTo = new int[G.V()];
marked = new boolean[G.V()];
for(int v=0;v<G.V();v++)
if(!marked[v]) dfs(G,v);
}
private void dfs(Digraph G,int v){
onStack[v] = true;
marked[v] = true;
for(int w:G.adj(v))
if(this.hasCycle()) return;
else if(!marked[w]) {edgeTo[w] = v; dfs(G, w);}
else if(onStack[w]){
cycle = new Stack<Integer>();
for(int x = v;x!=w;x=edgeTo[x])
cycle.push(x);
cycle.push(w);
cycle.push(v);
}
onStack[v]=false;
}
public boolean hasCycle(){return cycle != null;}
public Iterable<Integer> cycle(){return cycle;}
}
|
4.2.4.3 顶点的深度优先次序与拓扑排序
public class Topological | |
---|
Topological(Digraph G) | 拓扑排序的构造函数 |
boolean isDAG() | G 是有向无环图吗 |
Iterable order() | 拓扑有序的所有顶点 |
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
| public class DepthFirstOrder{
private boolean[] marked;
private Queue<Integer> pre; //所有顶点的前序排序
private Queue<Integer> post; //所有顶点的后序排序
private Stack<Integer> reversePost; //所有顶点的递后序排序
public DepthFirstOrder(Digraph G){
pre = new Queue<Integer>();
post = new Queue<Integer>();
reversePost = new Stack<Integer>();
marked = new boolean[G.V()];
for(int v=0;v<G.V();v++)
if(!marked[v]) dfs(G,v);
}
private void dfs(Digraph G,int v){
pre.enqueue(v);
marked[v] = true;
for(int w:G.adj(v))
if(!marked[w]) {dfs(G, w);}
post.enqueue(v);
reversePost.push(v);
}
public Iterable<Integer> pre(){return pre;}
public Iterable<Integer> post(){return post;}
public Iterable<Integer> reversePost(){return reversePost;}
}
public class Topological
{
private Iterable<Integer> order; // 顶点的拓扑顺序
public Topological(Digraph G)
{
DirectedCycle cyclefinder = new DirectedCycle(G);
if (!cyclefinder.hasCycle())
{
DepthFirstOrder dfs = new DepthFirstOrder(G);
order = dfs.reversePost();
}
}
public Iterable<Integer> order() { return order; }
public boolean isDAG() { return order != null; }
}
|
4.2.5 有向图中的强连通性
两个顶点v和w互相可达
文章作者
lim
上次更新
2024-09-14
(2aae67a)
许可协议
CC BY-NC-ND 4.0