java最小树源码实例。如果一个图中所有点都是联通的,求最小树可以将图遍历完成,这里的最小是指边最少,跟边长没有关系。
算法利用深度优先遍历,记载每个遍历过的节点,将节点按照遍历顺序记录下来就是所谓的最小树。
关于深度优先遍历请参见深度优先遍历。
不过这里奇怪的是:
假如所有节点之间是双向联通的,只用生成一个数组,装入所有的节点,例如{‘a’,'b’,'c’,'d’,'d’}
然后每两个点之间的线段就是最小树的结果,即a –> b, b –> c, c –> d, d –> e
似乎不用图这样复杂的结构支撑。
不过这里还是给出了按照图来产生最小树的办法。
Graph.mst:返回最小树。
Graph.main:提供简单测试。
代码如下:
1
class Stack {
2
private int[] values;
3
private int pos = -1;
4
Stack(int size) {
5
values = new int[size];
6
}
7
void push(int value) { values[++pos] = value; }
8
int pop() { return values[pos--]; }
9
int peek() { return values[pos]; }
10
boolean isEmpty() { return pos == -1; }
11
}
12
13
class Vertex {
14
private Object value;
15
private boolean isVisited;
16
Vertex(Object value) {
17
this.value = value;
18
}
19
20
void visit() { isVisited = true; }
21
void clean() { isVisited = false; }
22
boolean isVisited() { return isVisited; }
23
Object value() { return value; }
24
}
25
26
class Graph {
27
private Vertex[] vertexs;
28
private int[][] adjMat;
29
private int pos = -1;
30
31
Graph(int size) {
32
vertexs = new Vertex[size];
33
adjMat = new int[size][size];
34
}
35
36
void add(Object value) {
37
assert pos < vertexs.length;
38
vertexs[++pos] = new Vertex(value);
39
}
40
41
void connect(int from, int to) {
42
adjMat[from][to] = 1;
43
adjMat[to][from] = 1;
44
}
45
46
void connectAll() {
47
for(int i=0; i<= pos; i++)
48
for(int j=0; j<= pos; j++)
49
adjMat[i][j] = i^j&1;
50
51
}
52
int findNeighbor(int index) {
53
for(int i=0; i<=pos; i++) {
54
if(adjMat[index][i] == 1 && !vertexs[i].isVisited()) return i;
55
}
56
return -1;
57
}
58
59
Object[] mst(int index) { //从指定下标的节点开始生成最小数
60
if(vertexs[index] == null) return new Object[0]; //如果图中没有指定下标节点,则退出
61
62
Stack s = new Stack(vertexs.length); //创建栈记载访问过的节点的下标
63
Object[] result = new Object[pos+1]; //返回的结果
64
int i = 0;
65
vertexs[index].visit(); //访问0节点
66
result[i++] = vertexs[index].value();
67
s.push(index); //记录0节点
68
69
while(!s.isEmpty()) { //如果还有记录的节点则继续
70
index = findNeighbor(s.peek()); //寻找栈顶节点的未访问过的邻居
71
if(index != -1) { //如果找到
72
vertexs[index].visit(); //访问该节点
73
result[i++] = vertexs[index].value();
74
s.push(index); //记录该节点
75
} else s.pop(); //没有未访问过的节点,则出栈
76
} //如果栈未空则代表遍历完成
77
clean(); //清除所有访问标致
78
return result;
79
}
80
81
void clean() { for(Vertex v: vertexs) if(v != null)v.clean(); }
82
83
public static void main(String[] args) {
84
Graph g = new Graph(20);
85
g.add(‘a’);
86
g.add(‘b’);
87
g.add(‘c’);
88
g.add(‘d’);
89
g.add(‘e’);
90
g.connectAll();
91
Object[] result = g.mst(0);
92
for(int i=0; i<result.length-1; i++) {
93
System.out.println(result[i] + ” –> ” + result[i+1]);
94
}
95
}
96
}
class Stack {2
private int[] values;3
private int pos = -1;4
Stack(int size) {5
values = new int[size];6
}7
void push(int value) { values[++pos] = value; }8
int pop() { return values[pos--]; }9
int peek() { return values[pos]; }10
boolean isEmpty() { return pos == -1; }11
}12

13
class Vertex {14
private Object value;15
private boolean isVisited;16
Vertex(Object value) {17
this.value = value;18
}19

20
void visit() { isVisited = true; }21
void clean() { isVisited = false; }22
boolean isVisited() { return isVisited; }23
Object value() { return value; }24
}25

26
class Graph {27
private Vertex[] vertexs;28
private int[][] adjMat;29
private int pos = -1;30

31
Graph(int size) {32
vertexs = new Vertex[size];33
adjMat = new int[size][size];34
}35

36
void add(Object value) {37
assert pos < vertexs.length;38
vertexs[++pos] = new Vertex(value);39
}40

41
void connect(int from, int to) {42
adjMat[from][to] = 1;43
adjMat[to][from] = 1;44
}45

46
void connectAll() {47
for(int i=0; i<= pos; i++)48
for(int j=0; j<= pos; j++)49
adjMat[i][j] = i^j&1;50

51
}52
int findNeighbor(int index) {53
for(int i=0; i<=pos; i++) {54
if(adjMat[index][i] == 1 && !vertexs[i].isVisited()) return i;55
}56
return -1;57
}58

59
Object[] mst(int index) { //从指定下标的节点开始生成最小数60
if(vertexs[index] == null) return new Object[0]; //如果图中没有指定下标节点,则退出61

62
Stack s = new Stack(vertexs.length); //创建栈记载访问过的节点的下标63
Object[] result = new Object[pos+1]; //返回的结果64
int i = 0;65
vertexs[index].visit(); //访问0节点66
result[i++] = vertexs[index].value();67
s.push(index); //记录0节点68

69
while(!s.isEmpty()) { //如果还有记录的节点则继续70
index = findNeighbor(s.peek()); //寻找栈顶节点的未访问过的邻居71
if(index != -1) { //如果找到72
vertexs[index].visit(); //访问该节点73
result[i++] = vertexs[index].value();74
s.push(index); //记录该节点75
} else s.pop(); //没有未访问过的节点,则出栈76
} //如果栈未空则代表遍历完成77
clean(); //清除所有访问标致78
return result;79
}80

81
void clean() { for(Vertex v: vertexs) if(v != null)v.clean(); }82

83
public static void main(String[] args) {84
Graph g = new Graph(20);85
g.add(‘a’);86
g.add(‘b’);87
g.add(‘c’);88
g.add(‘d’);89
g.add(‘e’);90
g.connectAll();91
Object[] result = g.mst(0);92
for(int i=0; i<result.length-1; i++) {93
System.out.println(result[i] + ” –> ” + result[i+1]);94
}95
}96
}