Skip to content

Commit 209fb6f

Browse files
author
Jiang Haifeng
committed
最小生成树
1 parent 92936a9 commit 209fb6f

File tree

8 files changed

+264
-42
lines changed

8 files changed

+264
-42
lines changed

GraphTheory/src/weight/DenseGraph.java

Lines changed: 12 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -5,21 +5,21 @@
55
import java.util.List;
66

77
// 稠密图 - 邻接矩阵
8-
public class DenseGraph<Weight> implements Graph<Weight> {
8+
public class DenseGraph implements Graph {
99
private int n, m; // n 为顶点 V,m 为边 E
1010

1111
// 指定是否为有向图
1212
private boolean directed;
1313

14-
List<List<Edge<Weight>>> g;
14+
List<List<Edge>> g;
1515

1616
public DenseGraph(int n, boolean directed) {
1717
this.n = n;
1818
this.m = 0;
1919
this.directed = directed;
2020
g = new ArrayList<>();
2121
for (int i = 0; i < n; i++) {
22-
List<Edge<Weight>> line = new ArrayList<>();
22+
List<Edge> line = new ArrayList<>();
2323
for (int j = 0; j < n; j++)
2424
line.add(null);
2525
g.add(line);
@@ -34,7 +34,7 @@ public int E() {
3434
return m;
3535
}
3636

37-
public void addEdge(int v, int w, Weight weight) {
37+
public void addEdge(int v, int w, double weight) {
3838
assert (v >= 0 && v < n);
3939
assert (w >= 0 && w < n);
4040

@@ -45,9 +45,9 @@ public void addEdge(int v, int w, Weight weight) {
4545
g.get(w).set(v, null);
4646
}
4747

48-
g.get(v).set(w, new Edge<>(v, w, weight));
48+
g.get(v).set(w, new Edge(v, w, weight));
4949
if (!directed)
50-
g.get(w).set(v, new Edge<>(w, v, weight));
50+
g.get(w).set(v, new Edge(w, v, weight));
5151

5252
m++;
5353
}
@@ -59,11 +59,11 @@ public boolean hasEdge(int v, int w) {
5959
return g.get(v).get(w) != null;
6060
}
6161

62-
public Iterable<Integer> adj(int v) {
63-
List<Integer> iter = new ArrayList<>();
62+
public Iterable<Edge> adj(int v) {
63+
List<Edge> iter = new ArrayList<>();
6464
for (int index = 0; index < g.size(); index++)
6565
if (g.get(v).get(index) != null)
66-
iter.add(index);
66+
iter.add(g.get(v).get(index));
6767
return iter;
6868
}
6969

@@ -73,7 +73,7 @@ public String toString() {
7373
stringBuilder.append("weight.DenseGraph\n");
7474
stringBuilder.append("-----------\n");
7575
for (int i = 0; i < g.size(); i++) {
76-
List<Edge<Weight>> line = g.get(i);
76+
List<Edge> line = g.get(i);
7777
stringBuilder.append(i);
7878
stringBuilder.append(" : ");
7979
for (int j = 0; j < line.size(); j++) {
@@ -90,11 +90,11 @@ public String toString() {
9090
}
9191

9292
class adjIterator implements Iterator {
93-
private DenseGraph<Weight> G;
93+
private DenseGraph G;
9494
private int v;
9595
int index;
9696

97-
public adjIterator(DenseGraph<Weight> graph, int v) {
97+
public adjIterator(DenseGraph graph, int v) {
9898
this.G = graph;
9999
this.v = v;
100100
this.index = -1;

GraphTheory/src/weight/Edge.java

Lines changed: 13 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,15 @@
11
package weight;
22

3-
public class Edge<Weight> {
3+
public class Edge implements Comparable<Edge> {
44
private int a;
55
private int b;
6-
private Weight weight;
6+
private double weight;
77

88
public Edge() {
99

1010
}
1111

12-
public Edge(int a, int b, Weight weight) {
12+
public Edge(int a, int b, double weight) {
1313
this.a = a;
1414
this.b = b;
1515
this.weight = weight;
@@ -23,7 +23,7 @@ public int w() {
2323
return b;
2424
}
2525

26-
public Weight wt() {
26+
public double wt() {
2727
return weight;
2828
}
2929

@@ -32,4 +32,13 @@ public int other(int x) {
3232
return x == a ? b : a;
3333
}
3434

35+
@Override
36+
public int compareTo(Edge o) {
37+
return Double.compare(this.wt(), o.wt());
38+
}
39+
40+
@Override
41+
public String toString() {
42+
return String.format("%d-%d %.2f", a, b, wt());
43+
}
3544
}

GraphTheory/src/weight/Graph.java

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,15 @@
11
package weight;
22

3-
public interface Graph<Weight> {
3+
import java.util.List;
4+
5+
public interface Graph {
46
public int V();
57

68
public int E();
79

8-
public void addEdge(int v, int w, Weight weight);
10+
public void addEdge(int v, int w, double weight);
911

1012
public boolean hasEdge(int v, int w);
1113

14+
public Iterable<Edge> adj(int v);
1215
}

GraphTheory/src/weight/LazyPrimMST.java

Lines changed: 67 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,8 @@
11
package weight;
22

3+
import java.util.ArrayList;
4+
import java.util.List;
5+
36
public class LazyPrimMST {
47
/*
58
* 最小生成树问题 Minimum Span Tree
@@ -20,4 +23,68 @@ public class LazyPrimMST {
2023
* 切分定理(Cut Property):
2124
* 给定任意切分,横切边中最小的边,必然属于最小生成树。
2225
* */
26+
private Graph G;
27+
MinHeap<Edge> pq;
28+
29+
// 标记是否已经访问过
30+
boolean[] marked;
31+
32+
// 最小生成树
33+
List<Edge> mst;
34+
// 最小生成树对应总权值
35+
double mstWeight;
36+
37+
public LazyPrimMST(Graph G) {
38+
this.G = G;
39+
this.pq = new MinHeap<>(this.G.E());
40+
41+
marked = new boolean[G.V()];
42+
for (int i = 0; i < G.V(); i++) {
43+
marked[i] = false;
44+
}
45+
mst = new ArrayList<>();
46+
47+
// Lazy Prim
48+
visit(0);
49+
while (!pq.isEmpty()) {
50+
Edge e = pq.delMin();
51+
52+
// if (marked[e.v()] == marked[e.w()]) continue;
53+
if (marked[e.v()] && marked[e.w()]) continue;
54+
55+
mst.add(e);
56+
// if (!marked[e.v()])
57+
// visit(e.v());
58+
// else
59+
// visit(e.w());
60+
if (!marked[e.v()]) visit(e.v());
61+
if (!marked[e.w()]) visit(e.w());
62+
}
63+
64+
// 计算最小生成树总权值
65+
for (Edge e : mst) {
66+
mstWeight += e.wt();
67+
}
68+
}
69+
70+
private void visit(int v) {
71+
assert (!marked[v]);
72+
marked[v] = true;
73+
74+
Iterable<Edge> iterable = G.adj(v);
75+
for (Edge e : iterable) {
76+
if (!marked[e.other(v)])
77+
pq.insert(e);
78+
}
79+
80+
81+
}
82+
83+
public List<Edge> mstEdges() {
84+
return mst;
85+
}
86+
87+
public double reuslt() {
88+
return mstWeight;
89+
}
2390
}

GraphTheory/src/weight/Main.java

Lines changed: 82 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ private void adjIteratorMain() {
99
Random random = new Random();
1010

1111
// weight.SparseGraph
12-
SparseGraph<Integer> sparseGraph = new SparseGraph<>(N, false);
12+
SparseGraph sparseGraph = new SparseGraph(N, false);
1313
for (int i = 0; i < M; i++) {
1414
int a = random.nextInt(N);
1515
int b = random.nextInt(N);
@@ -31,7 +31,7 @@ private void adjIteratorMain() {
3131
System.out.println("----------分割线----------");
3232

3333
// weight.DenseGraph
34-
DenseGraph<Integer> denseGraph = new DenseGraph<>(N, false);
34+
DenseGraph denseGraph = new DenseGraph(N, false);
3535
for (int i = 0; i < M; i++) {
3636
int a = random.nextInt(N);
3737
int b = random.nextInt(N);
@@ -57,7 +57,7 @@ private void iteratorMain() {
5757
Random random = new Random();
5858

5959
// weight.SparseGraph
60-
SparseGraph<Integer> sparseGraph = new SparseGraph<>(N, false);
60+
SparseGraph sparseGraph = new SparseGraph(N, false);
6161
for (int i = 0; i < M; i++) {
6262
int a = random.nextInt(N);
6363
int b = random.nextInt(N);
@@ -69,8 +69,8 @@ private void iteratorMain() {
6969
// O(E)
7070
for (int v = 0; v < N; v++) {
7171
System.out.print(v + " : ");
72-
Iterable<Integer> iterator = sparseGraph.adj(v);
73-
for (Integer w : iterator) {
72+
Iterable<Edge> iterator = sparseGraph.adj(v);
73+
for (Edge w : iterator) {
7474
System.out.print(w + " ");
7575
}
7676
System.out.println();
@@ -79,7 +79,7 @@ private void iteratorMain() {
7979
System.out.println("----------分割线----------");
8080

8181
// weight.DenseGraph
82-
DenseGraph<Integer> denseGraph = new DenseGraph<>(N, false);
82+
DenseGraph denseGraph = new DenseGraph(N, false);
8383
for (int i = 0; i < M; i++) {
8484
int a = random.nextInt(N);
8585
int b = random.nextInt(N);
@@ -90,18 +90,91 @@ private void iteratorMain() {
9090
// O(V^2)
9191
for (int v = 0; v < N; v++) {
9292
System.out.print(v + " : ");
93-
Iterable<Integer> iterator = denseGraph.adj(v);
94-
for (Integer w : iterator) {
93+
Iterable<Edge> iterator = denseGraph.adj(v);
94+
for (Edge w : iterator) {
9595
System.out.print(w + " ");
9696
}
9797
System.out.println();
9898
}
9999
}
100100

101+
public void lazyPrimMst() {
102+
int N = 10;
103+
int M = 10;
104+
Random random = new Random();
105+
106+
// weight.SparseGraph
107+
SparseGraph sparseGraph = new SparseGraph(N, false);
108+
for (int i = 0; i < M; i++) {
109+
int a = random.nextInt(N);
110+
int b = random.nextInt(N);
111+
double weight = Math.random();
112+
sparseGraph.addEdge(a, b, weight);
113+
}
114+
System.out.println(sparseGraph);
115+
116+
117+
// O(E)
118+
// 打印所有边
119+
for (int v = 0; v < N; v++) {
120+
System.out.print(v + " : ");
121+
Iterable<Edge> iterator = sparseGraph.adj(v);
122+
for (Edge w : iterator) {
123+
System.out.print(w + " ");
124+
}
125+
System.out.println();
126+
}
127+
128+
// 打印最小生成树
129+
LazyPrimMST lazySparseGraphPrimMST = new LazyPrimMST(sparseGraph);
130+
Iterable<Edge> sparseGraphIterator = lazySparseGraphPrimMST.mstEdges();
131+
for (Edge w : sparseGraphIterator) {
132+
System.out.print(w + " ");
133+
}
134+
System.out.println();
135+
System.out.println(lazySparseGraphPrimMST.reuslt());
136+
137+
138+
System.out.println("----------分割线----------");
139+
140+
// weight.DenseGraph
141+
DenseGraph denseGraph = new DenseGraph(N, false);
142+
for (int i = 0; i < M; i++) {
143+
int a = random.nextInt(N);
144+
int b = random.nextInt(N);
145+
double weight = Math.random();
146+
denseGraph.addEdge(a, b, weight);
147+
}
148+
System.out.println(denseGraph);
149+
150+
// O(V^2)
151+
// 打印所有边
152+
for (int v = 0; v < N; v++) {
153+
System.out.print(v + " : ");
154+
Iterable<Edge> iterator = denseGraph.adj(v);
155+
for (Edge w : iterator) {
156+
System.out.print(w + " ");
157+
}
158+
System.out.println();
159+
}
160+
161+
// 打印最小生成树
162+
LazyPrimMST lazyDenseGraphPrimMST = new LazyPrimMST(denseGraph);
163+
Iterable<Edge> denseGraphIterator = lazyDenseGraphPrimMST.mstEdges();
164+
for (Edge w : denseGraphIterator) {
165+
System.out.print(w + " ");
166+
}
167+
System.out.println();
168+
System.out.println(lazyDenseGraphPrimMST.reuslt());
169+
170+
}
171+
172+
101173
public static void main(String[] args) {
102174
Main main = new Main();
103175
// main.adjIteratorMain();
104-
main.iteratorMain();
176+
// main.iteratorMain();
177+
main.lazyPrimMst();
105178

106179
}
107180
}

0 commit comments

Comments
 (0)