Prim算法求村子间修路最短路径问题:
- 1、首先得有一个图的类,属性包括:图的节点个数、节点数据(A、B、C、D村)、节点间的关系(二维数组邻接矩阵)
- 2、利用上面图的这个类,构建一个图(和链表的节点构建链表、数的结点构建数类似)
- 3、显示这个图的邻接矩阵(村子间路的长度的关系)
- 4、prim算法
- 4.1、肯定需要定义一个visited[] 数组,用来表示以及访问过的节点,下标表示不同节点,值=0表示没访问过,值=1表示访问过了
- 4.2、写个双重for循环来遍历邻接矩阵中的每一种可能。
-
- 4.2.1 需要的是上面所有可能中:visited[i]==1&&visited[j]==0的情况,即一个顶点已经访问过,和这个顶点相连的没访问过的顶点 连成的边
-
- 4.2.2 还要缩小范围到一个最小值:graph.weight[i][j] < minWeight(连成的边有多条,找最小值)
- 4.3、双重循环结束后,找到的是一条最小的边,有 graph.verxs顶点,普利姆算法结束后,有 graph.verxs-1边,所以外面再加一个循环
- 4.4、将当前这个结点(4.2找到的)标记为已经访问
- 4.5、minWeight 重新设置为最大值 10000(遍历过程中一直被换成越来越小的,最小的就是找到的值)
package cn.edu.uestc.Prim;
import java.util.Arrays;
public class PrimAlgorithm {
public static void main(String[] args) {
MinTree minTree = new MinTree();
char[] data = {'A','B','C','D','E','F','G'};
int vertex = data.length;
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},
};
MGraph mGraph = new MGraph(vertex);
//要什么给什么
minTree.createGraph(mGraph,vertex,data,weight);//这个方法只是对mGraph初始化
minTree.showGraph(mGraph);
minTree.prim(mGraph,0);
}
}
class MinTree{//最小生成数(各个村子的连接图)
/**
* 利用MGraph创建图
*/
public void createGraph(MGraph mGraph, int vertex, char data[], int[][] weight){
mGraph.vertex = vertex;
mGraph.date = data;
mGraph.weight = 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];
}
}*/
}
/**
* 显示图的邻接矩阵
* @param mGraph
*/
public void showGraph(MGraph mGraph){
for (int[] data : mGraph.weight){
System.out.println(Arrays.toString(data));
}
}
/**
* prim算法,得到最小生成数
* @param v 表示从图的第几个顶点开始生成'A'->0 'B'->1...
*/
public void prim(MGraph mGraph, int v){
int visited[] = new int[mGraph.vertex];
visited[v] = 1;//从这个开始,这个第一个标记为已经访问,后续从这个点开始找最近的路修路
int minWeight = 10000;
int[][] weight = mGraph.weight;
int h1 = 0;//存放i、j(即村子对应矩阵下标是哪一个)
int h2 = 0;
for (int k = 1; k < mGraph.vertex; k++) { //根据prim算法,有vertex个顶点,最后就会有vertex-1条边
for (int i = 0; i < mGraph.vertex; i++) {
for (int j = 0; j < mGraph.vertex; j++) {
if (visited[i] == 1 && visited[j] == 0 && weight[i][j] < minWeight) {
h1 = i;
h2 = j;
minWeight = weight[i][j];
}
}
}
//双重for循环结束后,完成的是一条最佳路径的寻找,下次寻找还得重新来。另外,这时候j也成为已经访问过的了
minWeight = 10000;
visited[h2] = 1;
//每次二重for都生成了一条我们要的路
System.out.println(mGraph.date[h1] + " 村与 " + mGraph.date[h2] + " 村完成修路,长度为: " + weight[h1][h2]);
}
}
}
class MGraph{
int vertex;//英文单词 顶点的意思, 这里表示节点个数
char[] date; // 节点的值:A村、B村、C村....
int[][] weight; //存放边,就是邻接矩阵
public MGraph(int vertex) {
this.vertex = vertex;
date = new char[vertex];
weight = new int[vertex][vertex];
}
}