应用场景-修路问题
1.有7个村庄(A, B, C, D, E, F, G) ,现在需要修路把7个村庄连通
2. 各个村庄的距离用边线表示(权) ,比如 A – B 距离 5公里
3. 问:如何修路保证各个村庄都能连通,并且总的修建公路总里程最短?
思路: 将10条边,连接即可,但是总的里程数不是最小.
正确的思路,就是尽可能的选择少的路线,并且每条路线最小,保证总里程数最少.
/**
* 图的结构的实现主要是 领接矩阵 和邻接表, 矩阵存在浪费很多空间 , 不是特别好的, 所以我们使用邻接表 实现
* 普里姆 算法, 找到一个最短路径联通整个村庄的路,
*
*/
public class Test1 {
public static void main(String[] args) {
/**
* 上图为邻接矩阵的表达方式, 10000表示为空 A-B 的距轻松可以看到是 5
* a b c d e f g
*
* a 10000 5 7 10000 10000 10000 2
* b 5 10000 10000 9 10000 10000 3
* c 7 10000 10000 10000 8 10000 10000
* d 10000 9 10000 10000 10000 4 10000
* e 10000 10000 8 10000 10000 5 4
* f 10000 10000 10000 4 5 10000 6
* g 2 3 10000 10000 4 6 10000
*/
/**
* 使用邻接表表达以上数据结构
*/
Map<String, PointPower[]> map = new HashMap<String, PointPower[]>();
map.put("A", new PointPower[]{
new PointPower("B", 5),
new PointPower("C", 7),
new PointPower("G", 2),
});
map.put("B", new PointPower[]{
new PointPower("A", 5),
new PointPower("D", 9),
new PointPower("G", 3),
});
map.put("C", new PointPower[]{
new PointPower("A", 7),
new PointPower("E", 8),
});
map.put("D", new PointPower[]{
new PointPower("B", 9),
new PointPower("F", 4),
});
map.put("E", new PointPower[]{
new PointPower("C", 8),
new PointPower("F", 5),
new PointPower("G", 4),
});
map.put("F", new PointPower[]{
new PointPower("D", 4),
new PointPower("E", 5),
new PointPower("G", 6),
});
map.put("G", new PointPower[]{
new PointPower("A", 2),
new PointPower("B", 3),
new PointPower("E", 4),
new PointPower("F", 6),
});
// 开始从那个点开始找
List<String> startPointList = new ArrayList<>();
startPointList.add("A");
// 当前访问的元素
String startPoint = null;
// 访问过的元素
Set<String> visited = new HashSet<>();
// 这个循环就是表示输出多少条边
for (int i = 0; i < map.size() -1; i++) {
// 找到最小的元素索引
int minIndex = Integer.MAX_VALUE;
// 最小元素的权值
int minPower = Integer.MAX_VALUE;
// 最小元素所在点
String minPoint = null;
for (int x = 0; x < startPointList.size(); x++) {
startPoint = startPointList.get(x);
// 获得起始点的所有边
PointPower[] pointPowers = map.get(startPoint);
for (int j = 0; j < pointPowers.length; j++) {
PointPower thisPower = pointPowers[j];
if (thisPower.power < minPower && !visited.contains(thisPower.pint) ) {
minIndex = j;
minPower = pointPowers[j].power;
minPoint = startPoint;
}
}
}
PointPower[] pointPowers = map.get(minPoint);
System.out.println("边=" + minPoint + " --> " + pointPowers[minIndex].pint + ",权值:" + pointPowers[minIndex].power);
visited.add(minPoint);
visited.add(pointPowers[minIndex].pint);
startPointList.add(pointPowers[minIndex].pint);
}
}
}
/**
* 这是一个点和权值得类
*/
class PointPower {
// 表示这个点的名称
String pint;
// 表示这个点距离下一个点的权
int power;
public PointPower(String pint, int power) {
this.pint = pint;
this.power = power;
}
}