基本介紹
普里姆算法(Prim算法),圖論中的一種算法,可在加權連通圖里搜索最小生成樹。意即由此算法搜索到的邊子集所構成的樹中,不但包括了連通圖里的所有頂點(英語:Vertex (graph theory)),且其所有邊的權值之和亦為最小。該算法於1930年由捷克數學家沃伊捷赫·亞爾尼克(英語:Vojtěch Jarník)發現;並在1957年由美國計算機科學家羅伯特·普里姆(英語:Robert C. Prim)獨立發現;1959年,艾茲格·迪科斯徹再次發現了該算法。因此,在某些場合,普里姆算法又被稱為DJP算法、亞爾尼克算法或普里姆-亞爾尼克算法。
案例
1)有勝利鄉有7個村庄(A, B, C, D, E, F, G) ,現在需要修路把7個村庄連通
2)各個村庄的距離用邊線表示(權) ,比如 A – B 距離 5公里
3)問:如何修路保證各個村庄都能連通,並且總的修建公路總里程最短?
最小生成樹
這個問題本質上就是最小生成樹問題,最小生成樹:一個有 n 個結點的連通圖的生成樹是原圖的極小連通子圖,且包含原圖中的所有 n 個結點,並且有保持圖連通的最少的邊。最小生成樹可以用kruskal(克魯斯卡爾)算法或prim(普里姆)算法求出。
思路
代碼
import java.util.Arrays;
public class PrimAlgorithm {
public static void main(String[] args) {
char[] data = {'A','B','C','D','E','F','G'};
int [][]weight=new int[][]{ //10000表示不通
{10000,5,7,10000,10000,10000,2},
{5,10000,10000,9,10000,10000,3},
{7,10000,10000,10000,8,10000,10000},
{10000,9,10000,10000,10000,4,10000},
{10000,10000,8,10000,10000,5,4},
{10000,10000,10000,4,5,10000,6},
{2,3,10000,10000,4,6,10000},};
int vertex = data.length;
MGraph graph = new MGraph(vertex);
MinTree minTree = new MinTree();
minTree.createGraph(graph,vertex,data,weight);
minTree.showGraph(graph);
minTree.prim(graph,0);
}
}
class MGraph {
int vertex; //頂點個數
char[] data; //存放頂點
int[][] weight; //鄰接矩陣
public MGraph(int vertex) {
this.vertex = vertex;
weight = new int[vertex][vertex];
data = new char[vertex];
}
}
class MinTree {
/**
* 創建圖的鄰接矩陣
* @param graph 圖對象
* @param vertex 圖頂點個數
* @param data 圖的頂點的值
* @param weight 圖對應的鄰接矩陣
*/
public void createGraph(MGraph graph,int vertex,char[] data,int[][] weight) {
int i, j;
for(i = 0; i < vertex; i++) {
graph.data[i] = data[i];
for(j = 0; j < vertex; j++) {
graph.weight[i][j] = weight[i][j];
}
}
}
/**
* 顯示圖的鄰接矩陣
* @param graph 圖對象
*/
public void showGraph(MGraph graph) {
for (int[] link : graph.weight) {
System.out.println("link = " + Arrays.toString(link));
}
}
/**
* 普利姆算法
* @param graph 圖對象
* @param v 表示從哪個頂點開始
*/
public void prim(MGraph graph,int v) {
int[] visited = new int[graph.vertex]; //0表示未使用,1表示已使用
visited[v] = 1;
int index1 = 0;
int index2 = 0;
int minWeight = Integer.MAX_VALUE; //假設最小權值
for (int i = 1; i < graph.vertex; i++) {
for (int j = 0; j < graph.vertex; j++) {
for (int k = 0; k < graph.vertex; k++) {
if (visited[j] == 1 && visited[k] == 0 && graph.weight[j][k] < minWeight) {
minWeight = graph.weight[j][k];
index1 = j;
index2 = k;
}
}
}
System.out.println("邊為=>" + graph.data[index1] + ">" + graph.data[index2] + ",權值是" + minWeight);
visited[index2] = 1;
minWeight = Integer.MAX_VALUE;
}
}
}