java实现prim(普里姆)最小生成树
思路是这样: (思路大可不看,网上都是)
1、首先一个网,比如0-9为10个顶点嘛,(脑海中)让他里面的顶点都在集合V中,然后先找一个源点0
2、然后把这个源点0放在你的脑海中的集合S中,然后剩下的1-9顶点都放在脑海中的V-S里面。
3、然后就遍历S里面所有点与V-S中的邻接顶点的权值,找出权值最小的那个,把对应的V-S里面的那个顶点拉到S中。
比如:现在S中有0,他和顶点1,2,3互为邻接顶点,权值分别是5,6,7;那么就把顶点1放到S中。然后此时S中就有0和1两个顶点了。
还是比如:现在S中有0和1了,然后现在0和V-S中的2、3还是邻接顶点,权值为6、7。假如1和V-S中的邻接顶点是3、5,权值分别是1、4;那么这些权值里面最小的就是1,即顶点1和3之间的权值,就把3放到S中。。。。。
4、重复上面的步骤。最后把所有的顶点都放在S中,这个S就是个最小生成树了。
原理大家肯定都懂,上面的可看可不看,直接来看代码吧还是
当然这个代码里面我打印了每一步的步骤方便大家和我自己理解,大家复制即可运行,观察打印结果应该就差不多懂了。
import java.util.Arrays;
public class Prim {
public static void main(String[] args) {
int v=10; //这个是有几个顶点
int [][]g=new int[v][v]; //这个是建一个二维数组,就是邻接矩阵嘛,这里是无向图
for (int i = 0; i < v; i++) { //给所有的都赋值9999
for (int j = 0; j < v; j++) {
g[i][j] = 9999;
}
}
//然后给相连的点赋权值,这样如果两点之间权值是9999,就代表两点不相连
g[0][1]=1;
g[0][2]=3;
g[0][3]=3;
g[0][4]=5;
g[0][5]=4;
g[0][6]=6;
g[0][7]=9;
g[0][8]=8;
g[0][9]=7;
g[1][2]=7;
g[1][3]=5;
g[3][5]=11;
g[5][7]=13;
g[5][9]=7;
g[7][9]=5;
g[9][8]=9;
g[8][6]=11;
g[6][4]=10;
g[6][2]=14;
g[4][2]=5;
//无向图嘛,你连我我连你,然后就颠倒过来嘛。比如0和1的权值是1,那么1和0的也是1.
for (int i = 0; i < v; i++) {
for (int j = 0; j < v; j++) {
g[j][i] = g[i][j];
}
}
//这个是建立一个数组,存放生成最小树的顺序
int a[]=new int[v];
a=prim(g, 0);//调用方法,用a接着
System.out.println(Arrays.toString(a));//打印a
}
//实现代码如下
public static int[] prim(int g[][],int source) {
int[] visited=new int[g.length]; //首先定义一个数组记录是否被参观过,或者说是否在集合S中,亦或者说是否在最小生成树中
visited[0]=1;//0号是起始节点嘛,等于1说明他在最小树里面了已经,让它为1
int mst[]=new int[g.length];//建立一个装最小生成树结点的数组
for(int i=0;i<mst.length;i++) {
mst[i]=10000;//让里面的所有值都为1w,当然这个随你,1y也可
}
mst[0]=0;//0号已经在最小生成树里面,就让对应的位置为顶点的值0
for(int m=1;m<g.length;m++) {
int i=0;
int min=Integer.MAX_VALUE;
int index=0;
System.out.println("此时最小树有"+Arrays.toString(mst));
while(mst[i]!=10000) {//循环遍历一整个树找到和V-S中结点权值最小的那个。
for(int j=0;j<g.length;j++) {
System.out.println("现在遍历的是"+mst[i]+"和"+j+"结点");
if(visited[j]==0&&g[mst[i]][j]<min&&g[mst[i]][j]!=9999) {//如果这个顶点没有在最小树里面,然后权值更小就保存
System.out.println("此结点符合要求,最短路径由"+min+"更改为"+g[mst[i]][j]);
min=g[mst[i]][j];
index=j;
}else {
System.out.println("不合适或者不连通");
}
}
//上面for循环结束之后,会得到一个最小的min权值以及对应的顶点是谁。然后循环完集合最小生成树中的所有的权值,找到最小的
i++;
}
System.out.println("旧的最小生成树遍历完成,将V-S中离S最近的一个结点"+index+"放入新最小生成树中");
mst[i]=index;
visited[index]=1;
}
return mst;
}
}
这个代码我自己写的,谁也没参考,对不对我不知道哈
这个图我是这样画的,对不对不保证哈
运行的结果是这样的,每一次干的啥都打印出来了