普里姆算法应该是贪心算法的一种,具体体现在普里姆算法每一次都是找还最小连通图的最小的一个
import java.util.Arrays;
//普里姆算法
public class PrimDemo {
public static void main(String[] args) {
char[] data = new char[]{'A', 'B', 'C', 'D', 'E', 'F', 'G'};
int verxs = 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 mGraph = new MGraph(verxs);
//创建一个minTree对象
MinTree minTree = new MinTree();
minTree.createGraph(mGraph, verxs, data, weight);
// minTree.showGraph(mGraph);
minTree.prim(mGraph,1);
}
}
//创建最小生成树
class MinTree {
//创建图的邻接矩阵
/**
* @param graph 图对象
* @param verxs 图对应的顶点个数
* @param data 图的各顶点的值
* @param weights 图的邻接矩阵
*/
public void createGraph(MGraph graph, int verxs, char data[], int[][] weights) {
int i, j;
for (i = 0; i < verxs; i++) {
graph.data[i] = data[i];
for (j = 0; j < weights.length; j++) {
graph.weight[i][j] = weights[j][i];
}
}
}
//显示图的方法
public void showGraph(MGraph graph) {
for (int[] link : graph.weight) {
System.out.println(Arrays.toString(link));
}
}
//编写prim算法,得到最小生成树
//每次都是寻找未联通的边,中最小的
public void prim(MGraph graph, int v) {
//默认都为0
int visited[] = new int[graph.verxs];
//java可以不用写
for (int a : visited) {
a = 0;
}
//把当前这个结点标记为已访问
visited[v] = 1;
//h1和h2记录两个顶点的下标
int h1 = -1;
int h2 = -1;
int minWeight = 10000;//将minweight初始为一个大数
for (int k =1;k < graph.verxs; k++){//因为有graph.verxs顶点,普里姆算法结束之后,有graph.verxs-1边
//这是确定每一次生成的子树,和哪个顶点距离最近
for (int i = 0; i < graph.verxs; i++) {
for (int j = 0; j < graph.verxs; 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置为最大
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];
}
}
其中这段代码最能体现普利姆算法的精髓,思路如下
1.我们一共需要进行进行graph.verxs-1次循环,以为这样数量的边可以把他们连接成一个最小生成树.
2.之后两层for循环,找出有一个点访问了,令一个点没有访问的最小值
3.找到这个最小的边,标记起来同时标记这点为已经访问过,把最小值设置成最大值,方便下次循环的进行
for (int k =1;k < graph.verxs; k++){//因为有graph.verxs顶点,普里姆算法结束之后,有graph.verxs-1边
//这是确定每一次生成的子树,和哪个顶点距离最近
for (int i = 0; i < graph.verxs; i++) {
for (int j = 0; j < graph.verxs; 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置为最大
minWeight = 10000;