首先,该文档需要按照标准的markdown格式编写,包括使用合适的标题以及代码块。
本文将详细讲解Java实现最小生成树算法的详细攻略。最小生成树算法是指在一张无向图中,选出一些边将所有顶点连起来,并且这些边的权值之和最小。常用的最小生成树算法有Prim算法和Kruskal算法。
Prim算法
Prim算法的核心思想是:从一个顶点开始,每次选取一个未连接的权值最小的顶点加入生成树中,直到所有顶点都被加入。
示例说明:
假设有以下无向图,我们选择1号节点作为起点。
2---3
/| /|\
1 | / | \
\|/ | \
4---5----6
首先,我们将1号节点加入生成树中,然后选择与其相邻且权值最小的节点2加入。然后选择与1、2相邻且权值最小的节点4加入。此时,1、2、4都已经被连接成了一棵生成树,接下来选取与1、2、4相邻且权值最小的节点5加入,最后选择节点6加入,生成的最小生成树为:
2
/ \
1--4--5
\
6
Prim算法的实现
下面是Prim算法的Java实现代码,其中edges为邻接矩阵,n为节点个数。
public static void prim(int[][] edges, int n) {
boolean[] visited = new boolean[n]; // 记录节点是否被加入生成树
visited[0] = true; // 从0号节点开始遍历
int count = 1; // 记录已加入生成树的节点个数
while (count < n) {
int minWeight = Integer.MAX_VALUE;
int minFrom = -1;
int minTo = -1;
for (int i = 0; i < n; i++) {
if (visited[i]) {
for (int j = 0; j < n; j++) {
if (!visited[j] && edges[i][j] > 0 && edges[i][j] < minWeight) {
minWeight = edges[i][j];
minFrom = i;
minTo = j;
}
}
}
}
visited[minTo] = true;
count++;
System.out.println("Add edge: " + minFrom + "-" + minTo + " weight: " + minWeight);
}
}
Kruskal算法
Kruskal算法的核心思想是:将所有的边按照权值从小到大排序,依次选取每条边,如果该边连接的两个顶点在同一棵生成树中,则跳过该边,否则将该边加入生成树中。
示例说明:
假设有以下无向图,我们选择边的权值从小到大进行排序。
2---3
/| /|\
1 | / | \
\|/ | \
4---5----6
依次选取边(1,4)、(1,2)、(4,5)、(2,3)和(5,6),其中(2,3)连接的两个顶点已经在同一棵生成树中,应该跳过。最终生成的最小生成树为:
2
/ \
1--4--5
\
6
Kruskal算法的实现
下面是Kruskal算法的Java实现代码,其中edges为边集合,n为节点个数。
public static void kruskal(Edge[] edges, int n) {
Arrays.sort(edges); // 按权值从小到大排序
UnionFind uf = new UnionFind(n);
for (Edge edge : edges) {
if (uf.find(edge.from) != uf.find(edge.to)) { // 如果两个顶点不在同一棵生成树中
uf.union(edge.from, edge.to); // 按秩合并两个集合
System.out.println("Add edge: " + edge.from + "-" + edge.to + " weight: " + edge.weight);
}
}
}
static class Edge implements Comparable<Edge> {
int from;
int to;
int weight;
public Edge(int from, int to, int weight) {
this.from = from;
this.to = to;
this.weight = weight;
}
@Override
public int compareTo(Edge o) {
return Integer.compare(weight, o.weight);
}
}
static class UnionFind {
int[] parent;
int[] rank;
public UnionFind(int n) {
parent = new int[n];
rank = new int[n];
for (int i = 0; i < n; i++) {
parent[i] = i;
rank[i] = 1;
}
}
public int find(int x) {
if (parent[x] != x) {
parent[x] = find(parent[x]);
}
return parent[x];
}
public void union(int x, int y) {
int xRoot = find(x);
int yRoot = find(y);
if (xRoot == yRoot) {
return;
}
if (rank[xRoot] > rank[yRoot]) {
parent[yRoot] = xRoot;
} else if (rank[xRoot] < rank[yRoot]) {
parent[xRoot] = yRoot;
} else {
parent[xRoot] = yRoot;
rank[yRoot]++;
}
}
}
以上就是Java实现最小生成树算法的详细攻略,包括Prim算法和Kruskal算法的原理及Java实现示例。
本站文章如无特殊说明,均为本站原创,如若转载,请注明出处:Java实现最小生成树算法详解 - Python技术站