最小生成樹(java實現)


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


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章