package com.ldp.algorithm.demo04Prim; import org.junit.Test; import java.util.Arrays; /** * @create 06/05 6:24 * @description <p> * 普里母算法 * 案例修路问题,求修路的路径最短 * </p> */ public class Test01 { int dv = 10000; // 默认值10000表示不能连通(不修路) /** * 测试普里母算法 */ @Test public void test01() { // 定义节点 char[] nodeArray = {'A', 'B', 'C', 'D', 'E', 'F', 'G'}; // 使用二维数组表示各节点是否连通 int[][] weight = { {dv, 5, 7, dv, dv, dv, 2}, {5, dv, dv, 9, dv, dv, 3}, {7, dv, dv, dv, 8, dv, dv}, {dv, 9, dv, dv, dv, 4, dv}, {dv, dv, 8, dv, dv, 5, 4}, {dv, dv, dv, 4, 5, dv, 6}, {2, 3, dv, dv, 4, 6, dv}}; // 创建图对象 MyGraph myGraph = new MyGraph(nodeArray.length); // 创建一个minTree对象 MinTree minTree = new MinTree(); minTree.createGraph(myGraph, nodeArray, weight); // 数据显示 minTree.showGraph(myGraph); // 修路方案 minTree.prim(myGraph); } } /** * 创建最小生成树-->修路图 */ class MinTree { /** * 创建图的邻接矩阵 * * @param graph * @param nodeArray * @param weight */ public void createGraph(MyGraph graph, char[] nodeArray, int[][] weight) { int num = nodeArray.length; for (int i = 0; i < num; i++) { graph.nodeArray[i] = nodeArray[i]; for (int j = 0; j < num; j++) { graph.weight[i][j] = weight[i][j]; } } } /** * 显示图(矩阵),即遍历二维数组 * * @param myGraph */ public void showGraph(MyGraph myGraph) { int[][] weight = myGraph.weight; for (int[] ints : weight) { System.out.println(Arrays.toString(ints)); } } /** * 普里母算法 * * @param myGraph */ public void prim(MyGraph myGraph) { int dv = 10000; // 默认值10000表示不能连通(不修路) // 存放已经被访问过的点,默认为0表示没有被访问 int[] visited = new int[myGraph.num]; // 默认第一个节点已经被访问 visited[0] = 1; // h1 和 h2 记录两个节点的下标,给个默认值-1; int h1 = -1; int h2 = -1; // 表示默认节点h1到h2之间要修的路很长,即不通 int minWeight = dv; // 遍历所有需要访问的节点 // 为什么从1开始,因为默认第一个点是被访问了的 visited[0] = 1; for (int v = 1; v < myGraph.num; v++) { // 在所有已访问的节点 和 所有没有访问的节点中找到一条最短的路径 for (int i = 0; i < myGraph.num; i++) { // 表示已访问的节点下标 // 如果是没有被访问的几点就跳过 if (visited[i] != 1) { continue; } for (int j = 0; j < myGraph.num; j++) {// 没有被访问的节点下标 // 如果是已访问的几点就跳过 if (visited[j] == 1) { continue; } // 判定是否为最短 if (myGraph.weight[i][j] < minWeight) { minWeight = myGraph.weight[i][j]; h1 = i; h2 = j; } } } // 找到了一条最小边 System.out.println("需要修的路:" + myGraph.nodeArray[h1] + "->" + myGraph.nodeArray[h2] + ",长度为:" + minWeight); // 设置为已被访问 visited[h2] = 1; // 重置变量进行下一条路的选择 h1 = -1; h2 = -1; minWeight = dv; } } } /** * 图对象 */ class MyGraph { /** * 图节点个数 */ int num; /** * 节点数据,如: A,B,C... */ char[] nodeArray; /** * 使用二维数组(矩阵)表示每个节点的关系(路程长度) */ int[][] weight; /** * 构造器 * * @param num */ public MyGraph(int num) { this.num = num; this.nodeArray = new char[num]; this.weight = new int[num][num]; } }