修路问题的本质就是最小生成树问题,先介绍一下最小生成树(Minimum Cost Spanning Tree),简称MST
package L十大算法.Prime;
import java.util.Arrays;
/**
* @Author Zhou jian
* @Date 2020 ${month} 2020/1/15 0015 15:43
* 普利姆算法
*/
public class PrimeAlgrothim {
public static void main(String[] args) {
//测试看看图是否创建成功
char[] data = new char[]{'A','B','C','D','E','F','G'};
int verxs = data.length;
//邻接矩阵的关系使用二维数组表示,10000这个大数,表示两个点不联通
int [][]weight=new int[][]{
{10000,5,7,10000,10000,10000,2},
{5,10000,10000,9,10000,10000,3},
{7,10000,10000,10000,8,10000,10000},
{10000,9,10000,10000,10000,4,10000},
{10000,10000,8,10000,10000,5,4},
{10000,10000,10000,4,5,10000,6},
{2,3,10000,10000,4,6,10000},};
//创建Graph对象
MGraph mgraph = new MGraph(verxs);
//创建一个MiniTree
MinTree minTree = new MinTree();
minTree.createGraph(mgraph,verxs,data,weight);
//输出
minTree.showGraph(mgraph);
//测试普利姆水泥发
minTree.prime(mgraph,0);
}
}
//最小生成树---->村庄的图
class MinTree{
/**
*
* @param graph 图对象
* @param verxs 图对应的顶点个数
* @param data 图的各个顶点的值
* @param weight 图的临街矩阵
*/
//创建图的领结矩阵
public void createGraph(MGraph graph,int verxs,char[] data,int[][] weight){
int i,j;
for(i=0;i<verxs;i++){ //顶点
graph.data[i] = data[i];
for(j=0;j<verxs;j++){
graph.weight[i][j] = weight[i][j];
}
}
}
//显示图的临街矩阵
public void showGraph(MGraph graph){
for(int i=0;i<graph.verxs;i++){
for(int[] link : graph.weight){
System.out.println(Arrays.toString(link));
}
}
}
//编写prime算法,得到最小生成树
/*
* @param graph 图
* @param v 表示从图的第几个顶点开始生成'A'->0
*/
public void prime(MGraph graph,int v){
//visited[] 标记节点(顶点)是否访问过
int[] visited = new int[graph.verxs];
//visited[] 默认元素值都是0,表示没有访问过
for(int i=0;i<graph.verxs;i++){
visited[i]=0;
}
//把当前节点标记为已经访问
visited[v]=1;
//h1和h2记录这两个顶点下标
int h1 = -1;
int h2 = -1;
//将minWeight初始化为最大值,后面再遍历过程中,会被替换
int minWeight = 10000;
for(int k=1;k<graph.verxs;k++){ //因为有graph.verxs顶点,普利斯木算法结束后,有graph.versx-1边
//这个是确定每一次生成的子图和哪个节点的距离最近
for(int i=0;i<graph.verxs;i++){//遍历已经访问的节点;i节点表示被访问过的结案
for(int j=0;j<graph.verxs;j++){ //遍历没有访问的节点;j表示还没有被访问
if(visited[i]==1&&visited[j]==0&&graph.weight[i][j]<minWeight){
//替换minWeight(寻找已经访问过的节点和未访问过的节点间的权值最小的边)
minWeight = graph.weight[i][j];
h1 = i;
h2 = j;
}
}
}
//找到一条边最小
System.out.println("边<"+graph.data[h1]+","+graph.data[h2]+">权值"+minWeight);
//将当前节点标记为已经访问
visited[h2]=1;
//minWeight重新设置为最大值10000
minWeight=10000;
}
}
}
class MGraph{
int verxs; //表示图的节点的个数
char[] data;//存放节点数据
int[][] weight; //存放边,就是我们的邻近矩阵
public MGraph(int verxs) {
this.verxs = verxs;
data = new char[verxs];
weight = new int[verxs][verxs];
}
}