【JAVA演算法】圖論演算法 --求最小生成樹Prim演算法

focus.zhaos發表於2018-03-28

寫在前面:

    我也是一名java語言的愛好者,僅以此文作為學習的記錄,對於文中出現的程式碼規範,程式碼格式,演算法效率等問題,希望各路大神不吝賜教,在下感激不盡。同是學習的同學也同樣希望互相交流,取長補短。                                                                                                                                            

——zsferrier@126.com

    


大體上來說,一個無向圖G的最小生成樹就是由該圖的那些連線G的所有頂點的邊構成的樹,且其總價值最低

Prim演算法

    計算最小生成樹的一種方法是使其連續的一步步的長成,每一步都要把一個節點當作根並往上加邊。在演算法的任意時刻,我們都可以看到一組已經新增到樹上的節點,而其餘頂點尚未加到這棵樹中。此時,演算法在每一時刻都可以通過選擇邊(u,v)使得(u,v)的值是所有u在樹上但v不在樹上的邊的值中的最小值而找出一個新的頂點新增到這棵樹中。


演算法設計:

    Prim演算法基本和求最短路徑的Dijsktra演算法相同,設計資料型別時,對每個頂點保留dist和path以及一個known指標(表示頂點已知或未知)。這裡dist是連線到已知頂點最短邊的權,path是導致該頂點改變的最後頂點。

  資料型別:

	private static int MaxLen = 1000;
	private static Vertex[] verArray = new Vertex[7];
	class Vertex{
		public List<Integer> adjacency;
		public boolean known;
		public int dist;
		public Vertex path;
		public int vname;
		public Vertex(){
			known = false;
			dist = MaxLen;
			path = null;
		}
	}

演算法虛擬碼

//Prim演算法虛擬碼:
/**
 * Prim(Vertex s){
 * 		s.dist = 0;
 * 		while(there is an unknown vertex here){
 * 			Vertex v = the smallest dist vertex;
 * 			v.known = true;
 * 			for each Vertex w adjacent to v if( !w.known ) {
 * 				int dvw = the distance bewteen v and w;
 * 				if(dvw<w.dist){
 * 					w.dist = dvw;
 * 					w.path = v;
 * 				}
 * 			}
 * 		}
 * }
 * 
 */

Java語言實現Prim演算法:

import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;

public class PrimA {

	/**
	 * @param args
	 */
	private static int MaxLen = 1000;
	private static Vertex[] verArray = new Vertex[7];
	class Vertex{
		public List<Integer> adjacency;
		public boolean known;
		public int dist;
		public Vertex path;
		public int vname;
		public Vertex(){
			known = false;
			dist = MaxLen;
			path = null;
		}
	}
	//判斷是否還有unknown vertex存在
	public static boolean Judge(){
		for (Vertex v : verArray) {
			if (v.known==false) {
				return true;
			}
		}
		return false;
	}
	//返回Dist最小的unknown vertex
	public static Vertex SmallestVertex(){
		int Vnum = 0;
		int value = MaxLen;
		for(int i=0;i<7;i++){
			if((!verArray[i].known)&&(verArray[i].dist<value)){
				Vnum = i;
				value = verArray[i].dist;
			}
		}
		return verArray[Vnum];
	}
	public static void Prim(Vertex s){
		s.dist = 0;
		while(Judge()){
			Vertex v = SmallestVertex();
			v.known = true;
			for (Integer i : v.adjacency) {
				if ((!verArray[v.adjacency.indexOf(i)].known)&&(i<verArray[v.adjacency.indexOf(i)].dist)) {
					verArray[v.adjacency.indexOf(i)].dist = i;
					verArray[v.adjacency.indexOf(i)].path = v;
				}
			}
		}
	}
	public static void printTree(Vertex s){
		System.out.println("最小生成樹為:");
		for (Vertex v : verArray) {
			
			if (v!=s) {
				System.out.println("V"+v.vname+"-----"+"V"+v.path.vname+"     "+"邊權值為"+v.adjacency.get(v.path.vname));	
			}
		}
	}
	public static void main(String[] args) {
		// TODO Auto-generated method stub
		//初始化
		verArray[0] = new PrimA().new Vertex();
		verArray[1] = new PrimA().new Vertex();
		verArray[2] = new PrimA().new Vertex();
		verArray[3] = new PrimA().new Vertex();
		verArray[4] = new PrimA().new Vertex();
		verArray[5] = new PrimA().new Vertex();
		verArray[6] = new PrimA().new Vertex();
		verArray[0].adjacency = new ArrayList<Integer>(Arrays.asList(0,2,4,1,MaxLen,MaxLen,MaxLen));
		verArray[0].vname = 0;
		verArray[1].adjacency = new ArrayList<Integer>(Arrays.asList(2,0,MaxLen,3,10,MaxLen,MaxLen));
		verArray[1].vname = 1;
		verArray[2].adjacency = new ArrayList<Integer>(Arrays.asList(4,MaxLen,0,2,MaxLen,5,MaxLen));
		verArray[2].vname = 2;
		verArray[3].adjacency = new ArrayList<Integer>(Arrays.asList(1,3,2,0,7,8,4));
		verArray[3].vname = 3;
		verArray[4].adjacency = new ArrayList<Integer>(Arrays.asList(MaxLen,10,MaxLen,7,0,MaxLen,6));
		verArray[4].vname = 4;
		verArray[5].adjacency = new ArrayList<Integer>(Arrays.asList(MaxLen,MaxLen,5,8,MaxLen,0,1));
		verArray[5].vname = 5;
		verArray[6].adjacency = new ArrayList<Integer>(Arrays.asList(MaxLen,MaxLen,MaxLen,4,6,1,0));
		verArray[6].vname = 6;
		//起點從v0開始
		Prim(verArray[0]);
		printTree(verArray[0]);
	}

}

執行結果:






相關文章