Kruskal算法的JAVA实现

xiaoxiao2021-02-28  118

1.算法描述

克鲁斯卡尔算法需要对图的边进行访问,所以克鲁斯卡尔算法的时间复杂度只和边又关系,可以证明其时间复杂度为O(eloge)。

2.算法思想

1.将图各边按照权值进行排序

2.将图遍历一次,找出权值最小的边,(条件:此次找出的边不能和已加入最小生成树集合的边构成环),若符合条件,则加入最小生成树的集合中。不符合条件则继续遍历图,寻找下一个最小权值的边。

3.递归重复步骤1,直到找出n-1条边为止(设图有n个结点,则最小生成树的边数应为n-1条),算法结束。得到的就是此图的最小生成树。

3.JAVA代码

1)结构体定义 // 边的结构体 class ENode { char start; // 边的起点 char end; // 边的终点 int weight; // 边的权重 public ENode(char start, char end, int weight) { this.start = start; this.end = end; this.weight = weight; } }; // 邻接表中表的顶点 class VNode { char data; // 顶点信息 ENode firstEdge; // 指向第一条依附该顶点的弧 }; class Graph { private static final int INF = Integer.MAX_VALUE; // 最大值 char[] vertexs; // 顶点集合 int[][] matrix; // 邻接矩阵 // 得到当前有向图中的所有边信息 public List<ENode> getEdges() { List<ENode> edges = new ArrayList<ENode>(); for (int i = 0; i < vertexs.length; i++) { for (int j = 0; j < vertexs.length; j++) { if (matrix[i][j] != INF) { ENode edge = new ENode(vertexs[i], vertexs[j], matrix[i][j]); edges.add(edge); } } } return edges; } } 2)kruskal算法 private static final int INF = Integer.MAX_VALUE; // 最大值 static void qSort(List<ENode> edges, int low, int high) { if (low < high) { int i = low, j = high; ENode edge = edges.get(low); while (i < j) { while (edge.weight < edges.get(j).weight && i < j) j--; edges.set(i, edges.get(j)); while (edge.weight > edges.get(i).weight && i < j) i++; edges.set(j, edges.get(j)); } edges.set(i, edge); qSort(edges, low, i - 1); qSort(edges, i + 1, high); } } public static void kruskal(Graph G) { // 1.拿到有向图中所有边 List<ENode> edges = G.getEdges(); int edgeNum = edges.size(); // 2.对所有有向边进行排序 qSort(edges, 0, edgeNum - 1); ENode[] minTree = new ENode[G.vertexs.length - 1]; // 结果数组,保存kruskal最小生成树的边 int index = 0; // minTree数组的索引 // 用于保存"已有最小生成树"中每个顶点(以数组下标表示) 与 其经过“最短边”的邻接顶点 (以对应下标的值表示)的并查集 int[] start2end = new int[G.vertexs.length]; // 3.依次将最短且不与T构成回路的边加入T集合 for (int i = 0; i < edgeNum; i++) { //得到当前最短边 在有向图G中的起始顶点与终结顶点的 下标 int p1 = getIndex(G, edges.get(i).start); // 获取第i条边的"起点"的序号 int p2 = getIndex(G, edges.get(i).end); // 获取第i条边的"终点"的序号 //分别得到在T集合中沿当前最短边的“起点”与“终点”遍历到的最后节点, //若加入当前最短边后T集合存在回路,则“起点”与“终点”遍历到的最后节点一定是同一节点 int m = getEnd(start2end, p1); // 获取p1在"已有的最小生成树"中的终点 int n = getEnd(start2end, p2); // 获取p2在"已有的最小生成树"中的终点 //当前最短边加入T集合后没有有回路 则将当前最短边加入T集合,并且记录当前最短边的“起点”与“终点” if (m != n) { start2end[m] = n; // “起点”即vends的数组下标与“终点”即vends的对应下标的值 minTree[index++] = edges.get(i); // 保存结果 } } } static int getIndex(Graph G, char ch) { int i = 0; for (; i < G.vertexs.length; i++) if (G.vertexs[i] == ch) return i; return -1; } static int getEnd(int start2end[], int i) { while (start2end[i] != 0) i = start2end[i]; return i; }

转载请注明原文地址: https://www.6miu.com/read-32209.html

最新回复(0)