您的位置:首页 > 编程语言 > Java开发

最小生成树(java实现)

2014-09-02 22:37 316 查看
/**
* 定义基本数据结构
* @author 小宇
*/

public class MGraph
{
//当边edges[i][j]不存在时,用null表示其值
public static final int NULL = 1000;
static final int MAXV = 100;
//边集
int[][] edges = new int[this.MAXV][this.MAXV];
//顶点数,和边数
int n,e;
}


/**
* 该结构用于克鲁斯卡尔算法
* @author 小宇
*/
public class EStruct implements Comparable<EStruct>
{
int begin;
int end;
int weight;
//用于给List<EStruct>排序,实现接口comparable方法
public int compareTo(EStruct e)
{
return this.weight - e.weight;
}

}


/**
* 生成邻接矩阵并输出
* @author 小宇
*
*/

public class CreateGraph {
public void createMat(MGraph g, int A[][], int n)
{
int i, j;
g.n = n;
g.e = 0;
for(i = 0; i < n; i++)
for(j = 0; j < n; j++)
{
g.edges[i][j] = A[i][j];
if(g.edges[i][j] != 1000)
g.e++;
}
}
//---------------------------------------------------
public void DispMat(MGraph g)
{
int i, j;
for(i = 0; i < g.n; i++)
{
for(j = 0; j < g.n; j++)
if(g.edges[i][j] == g.NULL)
System.out.print("-" + " ");
else
System.out.print(g.edges[i][j] + " ");
System.out.println();
}
}

}


import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
/**
* 核心算法
* 用prim算法及克鲁斯卡尔算法求解最小生成树
* @author 小宇
*
*/
public class MinimalSpanningTree {

static final int INF = 32767;

private  List<EStruct> eArray = new ArrayList<EStruct>();

//--------------------------------Prim算法--------------------------------
public void Prim(MGraph g, int v)
{
int[] lowcost = new int[g.n];
int min;
int[] closest = new int[g.n];
int i,j,k = 0;
for(i = 0; i < g.n; i++)
{
lowcost[i] = g.edges[v][i];
closest[i] = v;
}
for(i = 1; i < g.n; i++)
{
min = INF;
for(j = 0; j < g.n; j++)
if(lowcost[j] != 0 && lowcost[j] < min)
{
min = lowcost[j];
k = j;
}
System.out.println(  "边" + closest[k] + "," + k + "权值" + min);
lowcost[closest[k]] = 0;
lowcost[k] = 0;
for(j = 0; j < g.n; j++)
if(g.edges[k][j] != 0 && g.edges[k][j] < lowcost[j])
{
lowcost[j] = g.edges[k][j];
closest[j] = k;
}
}
}
//---------------------克鲁斯卡尔算法-----------------------------------------------
public void getEStruct(MGraph mgraph)
{
/**
* 用EStruct结构保存每条边
* 最后存于EStruct数组
* 然后用java类库提供方法排序
*/
for(int i = 0;i < mgraph.n; i++)
{
for(int j = 0; j < mgraph.n; j++)
{
//由于是无向图
if(j < i)
{
//如果begin:i , end: j ,的边存在
if(mgraph.edges[i][j] != mgraph.NULL)
{
//创建EStruct保存该边信息并加入List:eArray
EStruct estruct = new EStruct();
estruct.begin = i;
estruct.end = j;
estruct.weight = mgraph.edges[i][j];
eArray.add(estruct);
}
}
}
}
//用java类库提供方法排序
Collections.sort(eArray);
}

//查找连线顶点的尾部下标
public int find(int[] p,int f)
{
while(p[f] != 0)
f = p[f];
return f;
}

public void Kruskal(MGraph mgraph)
{
int i, n, m;
//parent数组用于判断数组边集是否形成环路
int[] parent = new int[eArray.size()];
//初始化数组为零
for(i = 0; i < eArray.size(); i++)
parent[i] = 0;
//循环生成最小生成树,最小生成树的边数为图的(顶点数 - 1)
for(i = 0; i  < mgraph.n - 1; i++)
{
n = find(parent, eArray.get(i).begin);
m = find(parent,eArray.get(i).end);
//如果n不等于m说明此边与现有生成树没有形成环路
if(n != m)
{
//将此边的表尾节点放入下标为起点的parent中
//表明此顶点已在生成树集合中
parent
= m;
System.out.println(eArray.get(i).begin + "," +  eArray.get(i).end + "  权:" + eArray.get(i).weight);
}
}
}
}


/**
* 测试代码
* 生成邻接矩阵->prim->kruskal
* @author 小宇
*
*/

public class Test
{
public static void main(String[] args)
{
MGraph mgraph = new MGraph();

int[][] array = new int[6][6];
for(int i = 0;i < 6; i++)
for(int j = 0;j < 6; j++)
array[i][j] = mgraph.NULL;
array[0][1] = 6;
array[1][0] = 6;
array[0][3] = 5;
array[3][0] = 5;
array[0][2] = 1;
array[2][0] = 1;
array[1][2] = 5;
array[2][1] = 5;
array[2][3] = 5;
array[3][2] = 5;
array[1][4] = 3;
array[4][1] = 3;
array[4][2] = 6;
array[2][4] = 6;
array[2][5] = 4;
array[5][2] = 4;
array[4][5] = 6;
array[5][4] = 6;
array[3][5] = 2;
array[5][3] = 2;

CreateGraph myGraph = new CreateGraph();

System.out.println("创建邻接矩阵:");
myGraph.createMat(mgraph,array, 6);
myGraph.DispMat(mgraph);

System.out.println("Prim算法生成最小生成树:");
MinimalSpanningTree mst = new MinimalSpanningTree();
mst.Prim(mgraph, 0);

mst.getEStruct(mgraph);
mst.Kruskal(mgraph);
}
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  数据结构