1. 程式人生 > >最小生成樹Prim演算法java實現

最小生成樹Prim演算法java實現

package prim;

import java.util.*;

public class PrimTest {
	
	public static void main(String[] args) {
//互動輸入圖的鄰接矩陣表示,為方便測試,直接給定了鄰接矩陣值
//		System.out.println("請輸入圖定點個數: ");
//		Scanner sc = new Scanner(System.in);
//		String line = sc.nextLine();
//		int n = Integer.parseInt(line);
//		System.out.println("請輸入圖的路徑長度: ");
// int[][] c = new int[n+1][n+1]; // for(int i = 0; i < n; i++) { // line = sc.nextLine(); // String[] ds = line.split(","); // for(int j = 0;j < ds.length; j++) { // c[i+1][i+1] = Integer.parseInt(ds[j]); // // } // } // System.out.println("一次構成樹的邊為: "); int n = 6; //c[i][j]表示從i到j的權, 自己到自己的權,以及不能直接到的值置-
1,方便後面處理 int[][] c = { {0,0,0,0,0,0}, {0,-1,6,1,5,-1,-1}, {0,6,-1,5,-1,3,-1}, {0,1,5,-1,5,6,4}, {0,5,-1,5,-1,-1,2}, {0,-1,3,6,-1,-1,6}, {0,-1,-1,4,2,6,-1} }; prim(n,c); } public static void prim(int n, int[][] c) { //lowcost[i] 表示 從1到i的最短權值 int[] lowcost = new
int[n+1]; //closest[i]的表示: 將整個節點空間定為V,已選的空間從S=1(只有第一個點)開始, j在V-S中,找到S裡離j最近的節點i ,就記錄在closest[j]int[] closest = new int[n+1]; //哪些節點已經進入S空間 boolean[] s = new boolean[n+1]; //節點1進入S中,此為初始化 s[1] = true; //初始化 for(int i = 2; i <= n; i++) { //初始化第一個節點到每個節點權值 lowcost[i] = c[1][i]; //初始化,因為S中只有1,所以每個V-S中的節點最近的S中的節點一定是1 closest[i] = 1; //這些節點都初始化為不在S中的狀態 s[i] = false; } //n-1次遍歷,把S空間擴充成V for(int i = 1;i < n; i++) { //記錄一個當前最小權值,不斷比較最終變為整個1次遍歷過程的最小權值 int min = Integer.MAX_VALUE; //初始化j,j其實代表的是V-S空間中被選進S的節點 //它的特徵是,它到S(任何節點)的權值比其他節點到S(同樣隨便哪個節點)都小 //這裡的思想就是貪心的概念,通過區域性最優可以得到全域性最優 int j = 1; //遍歷除了直接初始化在S中的1節點外的其他所有節點 for(int k = 2; k <= n; k++) { //不等於-1即,直接有權值,然後迭代出最小的lowcost,同時更新一些值。 //這裡舉例更容易說明,如lowcost[k]其實代表的是目前的S空間到k的最小權值,迭代找到了這個k,那麼 顯然 j就應該是k if(lowcost[k] != -1 && lowcost[k] < min && !s[k]) { min = lowcost[k]; j = k; } } //輸出這對連線,closest[j]記錄的其實就是達成lowcost[k]這一最小權值時,S中具體是哪個節點 System.out.println(closest[j] + "-" + j); //如此,把j納入S空間 s[j] = true; //j進入S空間後,更新除1節點外所有節點的狀態,他們到S的最小權值還得看看他們到 新進入的j是否更小 for(int k = 2; k <= n; k++) { if(!s[k] && c[j][k] != -1) { //這裡注意,如果lowcost[k]本來是-1 說明本來都不相連直接可以更新了 //這裡的邏輯要搞清楚,先判斷有必要更新麼?(c[j][k]!= -1),然後判斷 要麼c[j][k]比之前的權值更小,要麼原來都不相連(c[j][k] < lowcost[k] || lowcost[k] == -1) 此時進行更新! if(c[j][k] < lowcost[k] || lowcost[k] == -1) { //更新該節點最小的權值 lowcost[k] = c[j][k]; //更新該節點在S中最近的點 closest[k] = j; } } } } } }