找连通网的最小生成树,金典的有两种算法普里姆算法和克鲁斯卡尔算法。下面是文字描述的普里姆算法:设 N =(V,{E})是联通网,TE 是N上最小生成树中边的集合。算法从U = {U0}(U0∈V),TE = {} 开始。重复以下操作:在所有u∈U,v∈V-U的边(u,v)∈ E 中找一条权值最小的边(u0,v0)并入集合TE,同时v0并入U,直至U = V为止。此时TE必有n-1条边,则 T =(V,{TE})为最小生成树。
代码部分:
// Prim 算法
public int prim() {
// 第一步初始化
int tempSource = 0;
int[] tempDistanceArray = new int[numNodes];
for (int i = 0; i < numNodes; i++) {
tempDistanceArray[i] = weightMatrix.getValue(tempSource, i);
} // Of for i
int[] tempParentArray = new int[numNodes];
Arrays.fill(tempParentArray, tempSource);
// -1 不是父亲
tempParentArray[tempSource] = -1;
boolean[] tempVisitedArray = new boolean[numNodes];
tempVisitedArray[tempSource] = true;
// 第二步主要回路
int tempMinDistance;
int tempBestNode = -1;
for (int i = 0; i < numNodes - 1; i++) {
// 2.1找到最优结点
tempMinDistance = Integer.MAX_VALUE;
for (int j = 0; j < numNodes; j++) {
// 这个结点被访问就跳过
if (tempVisitedArray[j]) {
continue;
} // Of if
if (tempMinDistance > tempDistanceArray[j]) {
tempMinDistance = tempDistanceArray[j];
tempBestNode = j;
} // Of if
} // Of for j
tempVisitedArray[tempBestNode] = true;
// 2.2 为下一轮准备
for (int j = 0; j < numNodes; j++) {
// 结点被访问就跳过
if (tempVisitedArray[j]) {
continue;
} // Of if
// 这个结点不可达
if (weightMatrix.getValue(tempBestNode, j) >= MAX_DISTANCE) {
continue;
} // Of if
// 这里就是和Dijkastra算法不同之处
// 在整个矩阵中去找
if (tempDistanceArray[j] > weightMatrix.getValue(tempBestNode, j)) {
// 改变路径
tempDistanceArray[j] = weightMatrix.getValue(tempBestNode, j);
// 改变父亲
tempParentArray[j] = tempBestNode;
} // Of if
} // Of for j
// 测试
System.out.println("The selected distance for each node: " + Arrays.toString(tempDistanceArray));
System.out.println("The parent of each node: " + Arrays.toString(tempParentArray));
} // Of for i
int resultCost = 0;
for (int i = 0; i < numNodes; i++) {
resultCost += tempDistanceArray[i];
} // Of for i
// Step 3. Output for debug.
System.out.println("Finally");
System.out.println("The parent of each node: " + Arrays.toString(tempParentArray));
System.out.println("The total cost: " + resultCost);
return resultCost;
}