/**
* 定義基本數據結構
* @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[n] = 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);
}
}