Java 语言 最小生成树 Kruskal与Prim算法的应用

Java阿木 发布于 22 天前 2 次阅读


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算法在求解最小生成树中的应用。通过实现这两个算法,我们可以更好地理解最小生成树的概念及其在图论中的应用。在实际应用中,选择合适的算法取决于具体问题的需求和数据结构的特点。