Java语言中最小生成树:Kruskal与Prim算法的应用
最小生成树(Minimum Spanning Tree,MST)是图论中的一个重要概念,它指的是在一个无向连通图中,包含图中所有顶点的、权值之和最小的生成树。最小生成树在计算机科学、网络设计、数据结构等领域有着广泛的应用。本文将围绕Java语言,探讨Kruskal与Prim算法在求解最小生成树中的应用。
Kruskal算法
Kruskal算法是一种基于贪心策略的最小生成树算法。其基本思想是:按照边的权值从小到大排序,从最小的边开始,依次将边加入到生成树中,直到生成树包含所有顶点为止。
Kruskal算法步骤
1. 将所有边按照权值从小到大排序。
2. 初始化一个空的最小生成树T。
3. 遍历排序后的边,对于每条边:
- 检查这条边是否与T中的任意一条边构成环。
- 如果不构成环,将这条边加入到T中。
4. 重复步骤3,直到T包含所有顶点。
Java实现
java
import java.util.;
class Edge implements Comparable<Edge> {
int src, dest, weight;
public int compareTo(Edge compareEdge) {
return this.weight - compareEdge.weight;
}
}
class Graph {
int V, E;
List<Edge> edges;
public Graph(int V, int E) {
this.V = V;
this.E = E;
edges = new ArrayList<>();
}
public void addEdge(int src, int dest, int weight) {
Edge edge = new Edge();
edge.src = src;
edge.dest = dest;
edge.weight = weight;
edges.add(edge);
}
public void kruskalMST() {
Collections.sort(edges);
int[] parent = new int[V];
int[] rank = new int[V];
for (int i = 0; i < V; ++i) {
parent[i] = i;
rank[i] = 0;
}
int edgeCount = 0;
int minCost = 0;
while (edgeCount < V - 1) {
Edge nextEdge = edges.get(edgeCount++);
int x = find(parent, nextEdge.src);
int y = find(parent, nextEdge.dest);
if (x != y) {
union(parent, rank, x, y);
System.out.println("Edge " + nextEdge.src + "-" + nextEdge.dest + " added to MST. Weight = " + nextEdge.weight);
minCost += nextEdge.weight;
}
}
System.out.println("Minimum Cost Spanning Tree: " + minCost);
}
int find(int[] parent, int i) {
if (parent[i] == i)
return i;
return find(parent, parent[i]);
}
void union(int[] parent, int[] rank, int x, int y) {
int xRoot = find(parent, x);
int yRoot = find(parent, y);
if (rank[xRoot] < rank[yRoot])
parent[xRoot] = yRoot;
else if (rank[xRoot] > rank[yRoot])
parent[yRoot] = xRoot;
else {
parent[yRoot] = xRoot;
rank[xRoot]++;
}
}
}
public class KruskalMST {
public static void main(String[] args) {
int V = 5;
int E = 7;
Graph graph = new Graph(V, E);
graph.addEdge(0, 1, 10);
graph.addEdge(0, 2, 6);
graph.addEdge(0, 3, 5);
graph.addEdge(1, 3, 15);
graph.addEdge(2, 3, 4);
graph.addEdge(2, 4, 9);
graph.addEdge(3, 4, 20);
System.out.println("Following are the edges in the constructed MST");
graph.kruskalMST();
}
}
Prim算法
Prim算法是一种基于贪心策略的最小生成树算法。其基本思想是:从某个顶点开始,逐步扩展生成树,每次选择与已生成树连接的最小权值边。
Prim算法步骤
1. 选择一个顶点作为起点,初始化生成树T为只包含该顶点的树。
2. 对于T中的每个顶点v,计算v到T中所有顶点的最小权值边。
3. 选择最小权值边,将其加入到T中。
4. 重复步骤2和3,直到T包含所有顶点。
Java实现
java
import java.util.;
class Graph {
int V, E;
List<Edge> adj[]; // Adjacency List
public Graph(int V) {
this.V = V;
adj = new ArrayList[V];
for (int i = 0; i < V; ++i)
adj[i] = new ArrayList<>();
}
public void addEdge(int v, int w, int weight) {
Edge edge = new Edge();
edge.src = v;
edge.dest = w;
edge.weight = weight;
adj[v].add(edge);
}
public void primMST() {
int[] key = new int[V]; // Key values used to pick minimum weight edge in cut
boolean[] mstSet = new boolean[V]; // To keep track of vertices not yet included in MST
// Initialize all keys as INFINITE and mstSet[] as false
for (int i = 0; i < V; ++i) {
key[i] = Integer.MAX_VALUE;
mstSet[i] = false;
}
// Always include first 1st vertex in MST.
key[0] = 0; // Make key 0 so that this vertex is picked as first vertex
// The MST will have V vertices
for (int count = 0; count < V - 1; ++count) {
// Pick the minimum key vertex from the set of vertices
// not yet included in MST
int u = minKey(key, mstSet, V);
// Add the picked vertex to the MST Set
mstSet[u] = true;
// Update key value and parent index of the adjacent vertices of
// the picked vertex. Consider only those vertices which are not yet
// included in MST
for (int i = 0; i < adj[u].size(); ++i) {
Edge edge = adj[u].get(i);
int v = edge.dest;
// If v is not yet included in MST and weight of u-v is
// less than key[v], then update key[v] and parent[v]
if (!mstSet[v] && edge.weight < key[v]) {
key[v] = edge.weight;
}
}
}
// print the constructed MST
printMST(key, V);
}
int minKey(int[] key, boolean[] mstSet, int V) {
int min = Integer.MAX_VALUE, min_index = -1;
for (int v = 0; v < V; ++v)
if (!mstSet[v] && key[v] < min)
min = key[v], min_index = v;
return min_index;
}
void printMST(int[] key, int V) {
System.out.println("Edge tWeight");
for (int i = 1; i < V; ++i)
System.out.println(adj[i].get(0).src + " - " + adj[i].get(0).dest + " t" + key[i]);
}
}
class Edge {
int src, dest, weight;
}
public class PrimMST {
public static void main(String[] args) {
int V = 5;
Graph graph = new Graph(V);
graph.addEdge(0, 1, 2);
graph.addEdge(0, 2, 3);
graph.addEdge(1, 2, 6);
graph.addEdge(1, 3, 8);
graph.addEdge(1, 4, 5);
graph.addEdge(2, 4, 7);
graph.addEdge(3, 4, 9);
System.out.println("Following are the edges in the constructed MST");
graph.primMST();
}
}
总结
本文介绍了Java语言中Kruskal与Prim算法在求解最小生成树中的应用。通过实现这两个算法,我们可以更好地理解最小生成树的概念及其在图论中的应用。在实际应用中,选择合适的算法取决于具体问题的需求和数据结构的特点。
Comments NOTHING