普里姆算法是以顶点为起点来逐点找到各个顶点上的最小权值的边来构建最小生成树的。换一个思路我们也可以直接以边为目标取构建,因为权值是在边上。直接找最小权值的边来构建生成树也是很自然的想法,但是以边为基本来构建最小生成树的时候需要考虑是是否构成环路的问题。
import java.util.Scanner;
class Edge2{
int begin;
int end;
int weight;
public Edge2(int begin,int end,int weight)
{
this.begin=begin;
this.end=end;
this.weight=weight;
}
}
class Graph{ //图类
int[] point; //顶点矩阵
Edge2[] edge; //边集矩阵
int numPoint; //顶点数量
int numEdeges; //边的数量
public Graph() {}
public Graph(int numPoint,int numEdeges)
{
this.numEdeges=numEdeges;
this.numPoint=numPoint;
point=new int[numPoint];
edge=new Edge2[numEdeges];
}
//邻接矩阵的表示法
public static void createGraph1(Graph graph,int j,int k){
Scanner in=new Scanner(System.in);
for(int i=0;i<j;i++) {
System.out.println("请输入第"+(i+1)+"顶点的数据:");
graph.point[i]=in.nextInt(); //录入顶点数据
}
for(int i=0;i<k;i++) //录入所有的边值
{
System.out.println("请输入第"+(i+1)+"条边的两端顶点坐标:");
int p1=in.nextInt();
int p2=in.nextInt();
System.out.println("请输入这两个顶点之间的权值:");
int a2=in.nextInt();
graph.edge[i]=new Edge2(p1,p2,a2);
}
}
//利用直接插入排序对边集数组进行排序
public static void px(Graph a)
{
for(int i=0;i<a.numEdeges;i++)
{
int k=i;
for(int h=i-1;h>=0;h--)
{
if(a.edge[k].weight<a.edge[h].weight)
{
Edge2 ed;
ed=a.edge[k];
a.edge[k]=a.edge[h];
a.edge[h]=ed;
k--;
}
}
}
}
}
public class dsd {
//克鲁斯卡尔算法的实现函数
public static void MiniSpanTree_Kruskal(Graph a)
{
int parent[]=new int[a.numPoint]; //parent数组本质上是一个并查集
for(int i=0;i<a.numPoint;i++)
{
parent[i]=0; //将parent数组的数据全部初始化为0
}
for(int i=0;i<a.numEdeges;i++)
{
int m,n;
n=Find(parent,a.edge[i].begin);
m=Find(parent,a.edge[i].end);
if(n!=m)
{
parent[n]=m;
}
System.out.println(a.edge[i].begin+"->"+a.edge[i].end+"weight:"+a.edge[i].weight);
}
}
public static int Find(int[]a,int f) //该函数用来判断树的形成过程中是否形成了环
{
while(a[f]>0)
{
f=a[f];
}
return f;
}
public static void main(String[] args)
{
Graph graph=new Graph(9,15);
graph.createGraph1(graph, graph.numPoint, graph.numEdeges);
graph.px(graph);
MiniSpanTree_Kruskal(graph);
}
}