同样是求最小生成树克鲁斯卡尔算法的思想则转变了一下,以边为目标去生成最小数
这种感觉就像是结果等于10式子2*5也行,20/2也行,方式不同只看最后的结果
思想:按照权值的大小从小到大排序,选择n-1条边,并且不构成回路
过程:构造一个只含有n个节点的森林,然后从权值最小到最大选择边加入到森林中,使之不产生回路,直到森林变成树为止
import java.util.Arrays; public class KruskalCase { private int edgeNum;//边 private char[] vertexs;//顶点 private int[][] matrix;//邻接矩阵 private static final int INF = Integer.MAX_VALUE;//顶点不相同 public static void main(String[] args) { char[] vertexs = {'A', 'B', 'C', 'D', 'E', 'F', 'G'}; int[][] matrix = { {0, 12, INF, INF, INF, 16, 14}, {12, 0, 10, INF, INF, 7, INF,}, {INF, 10, 0, 3, 5, 6, INF,}, {INF, INF, 3, 0, 4, INF, INF}, {INF, INF, 5, 4, 0, 2, 8}, {16, 7, 6, INF, 2, 0, 9}, {14, INF, INF, INF, 8, 9, 0} }; KruskalCase kruskalCase = new KruskalCase(vertexs, matrix); // kruskalCase.print(); EData[] edges = kruskalCase.getEdges(); System.out.println(Arrays.toString(edges)); kruskalCase.sortEdges(edges); System.out.println(Arrays.toString(edges)); kruskalCase.kruskal(); } public KruskalCase(char[] vertexs, int[][] matrix) { int vlen = vertexs.length; this.vertexs = new char[vlen]; for (int i = 0; i < vertexs.length; i++) { this.vertexs[i] = vertexs[i]; } this.matrix = new int[vlen][vlen]; for (int i = 0; i < vlen; i++) { for (int j = 0; j < vlen; j++) { this.matrix[i][j] = matrix[i][j]; } } for (int i = 0; i < vlen; i++) { for (int j = i + 1; j < vlen; j++) { if (this.matrix[i][j] != INF) { edgeNum++; } } } } public void print() { for (int i = 0; i < vertexs.length; i++) { for (int j = 0; j < vertexs.length; j++) { System.out.printf("%12d", matrix[i][j]); } System.out.println(); } } //排序 private void sortEdges(EData[] edges) { for (int i = 0; i < edges.length - 1; i++) { for (int j = 0; j < edges.length - 1 - i; j++) { if (edges[j].weight > edges[j + 1].weight) { EData tmp = edges[j]; edges[j] = edges[j + 1]; edges[j + 1] = tmp; } } } } private int getPosition(char ch) { for (int i = 0; i < vertexs.length; i++) { if (vertexs[i] == ch) { return i; } } return -1; } private EData[] getEdges() { int index = 0; EData[] edges = new EData[edgeNum]; for (int i = 0; i < vertexs.length; i++) { for (int j = i + 1; j < vertexs.length; j++) { if (matrix[i][j] != INF) { edges[index++] = new EData(vertexs[i], vertexs[j], matrix[i][j]); } } } return edges; } /** * 判断终点是否相同 * * @param ends 记录各个顶点对应的终点是哪个 遍历中形成 * @param i 传入顶点对应的下标 * @return */ private int getEnd(int[] ends, int i) { while (ends[i] != 0) { i = ends[i]; } return i; } public void kruskal() { int index = 0;//最后结果数组索引 int[] ends = new int[edgeNum];//保存顶点的终点 EData[] rets = new EData[edgeNum];//保存最后结果 EData[] edges = getEdges();//所有边的集合 12 sortEdges(edges); for (int i= 0;i<edgeNum;i++){ int p1 = getPosition(edges[i].start); int p2 = getPosition(edges[i].end); int m = getEnd(ends, p1); int n = getEnd(ends, p2); if (m != n){ ends[m] = n;//设置 m 在最小生成树的终点 rets[index++] = edges[i];//一条边确认 } } for (int i = 0; i < index; i++) { System.out.println(rets[i]); } } } class EData { char start; char end; int weight; public EData(char start, char end, int weight) { this.start = start; this.end = end; this.weight = weight; } @Override public String toString() { return "EData[" + "<" + start + "," + end + "> = " + weight + ']'; } }