/**
* 最小生成树:找寻图中连接所有顶点的最短距离的路径
* 普里姆算法(prim)和克鲁斯卡尔算法(kruskal)
* v0 v1 v2 v3 v4 v5 v6 v7 v8
* v0 0 10 # # # 11 # # #
* v1 10 0 18 # # # 16 # 12
* v2 # # 0 22 # # # # 8
* v3 # # 22 0 20 # # 16 21
* v4 # # # 20 0 26 # 7 #
* v5 11 # # # 26 0 17 # #
* v6 # 16 # # # 17 0 19 #
* v7 # # # 16 7 # 19 0 #
* v8 # 12 8 21 # # # # 0
* #:代表2点之间无连接
*/
public class MixTree {
public String [] topPoint={"0","1","2","3","4","5","6","7","8"};
public int length=9;
//65535=没有边
public int[][] sides={
{0, 10,65535, 65535, 65535, 11,65535, 65535,65535},
{10,0, 18,65535, 65535, 65535, 16,65535,12},
{65535, 65535, 0, 22,65535, 65535, 65535, 65535,8},
{65535, 65535, 22,0, 20,65535, 65535, 16,21},
{65535, 65535, 65535, 20,0, 26,65535, 7,65535},
{11,65535, 65535, 65535, 26,0, 17,65535,65535},
{65535, 16,65535, 65535, 65535, 17,0, 19,65535},
{65535, 65535, 65535, 16,7, 65535, 19,0,65535},
{65535, 12,8, 21,65535, 65535, 65535, 65535,0}
};
public static void main(String[] args) {
MixTree mixTree=new MixTree();
mixTree.prim(new MGraph());
}
//适用用边数多的图
private void prim(MGraph g){
int maxLength=9,infinity=65535;
int min,j,k;
//相关顶点的下标
int adjvex[]=new int[maxLength];
//权值数组
int lowCost[]=new int[maxLength];
//初始化,此下标的顶点假如生成树
lowCost[0]=0;
adjvex[0]=0;
for (int i = 1; i < g.length; i++) {
//将v0顶点与之有边的权值存入数组
lowCost[i]=g.sides[0][i];
//初始化都为v0的下标
adjvex[i]=0;
}
//此时:lowCost={0 10 # # # 11 # # #},#=65535
//整个循环,构造最小生成树的过程
for (int i = 1; i < g.length; i++) {
min=infinity;
j=1;k=0;
// 循环全部顶点,找到当前lowCost数组中的最小值,
while (j<g.length){
if(lowCost[j]!=0 && lowCost[j] < min){
min=lowCost[j];
k=j;
}
j++;
}
//i=1 打印 (0,1)
System.out.println("("+adjvex[k]+","+k+")");
//将当前顶点的权值设置为0,表示此顶点已经完成任务
lowCost[k]=0;
for (j = 1; j < g.length; j++) {
//将k行的数据中小于lowCost数组数据,替换相同下标的lowCost数组 (关键)
//此时lowCost={0 0 # # # 11 # # #};
//k=1所以,g.sides[1][j]={10 0 18 # # # 16 # 12}
if(lowCost[j]!=0 && g.sides[k][j] < lowCost[j]){
//将较小权值存入lowCost
lowCost[j]=g.sides[k][j];
//下标为k的顶点存入adjvex
adjvex[j]=k;
}
}//这时lowCost={0 0 18 # # 11 16 # 12},adjvex={0,0,1,0,0,0,1,0,1},
// adjvex[2]=1表示lowCost[2]的权值是替换的,
}
}
}
//克鲁斯卡尔算法,检查是否有回路
private void kruskal(EdgeGraph g){
int n,m;
EdgeNode edges[]=g.edges;
int parent[]=new int[9];
for (int i = 0; i < g.lengthTop; i++) {
parent[i]=0;
}
for (int i = 0; i < g.lengthEdge; i++) {
n=find(parent,edges[i].getBegin());
m=find(parent,edges[i].getEnd());
//不等,则说明此边没有与现有生成树形成环路
if(n!=m){
//将此边的结尾顶点放入下标为起点的parent中
//表示此顶点已经在生成树集合中
parent[n]=m;
System.out.printf("(%d,%d) %d",edges[i].getBegin(),edges[i].getEnd(),edges[i].getWeight());
System.out.println();
}
}
}
/*
{1,5,8,7,7,8,0,0,6} new EdgeNode(5,6,17), 1,2,18
i=7 n=5,8,6 m=6
*/
//查找连线顶点的尾部下标,
private int find(int parent[],int f){
while (parent[f]>0){
f=parent[f];
}
return f;
}