import java.util.ArrayList;
/**
* @author xiwang2017
* @创建时间 2022/6/26 15:35
* @描述 prim算法实现
*/
public class Prim_MST {
public static void main(String[] args) {
Graph graph = new Graph(7);
char[] data = new char[]{'A', 'B', 'C', 'D', 'E', 'F', 'G'};
Node[][] edges = new Node[][]{//应该写个转换方法的,自己想ABC啥的下标太累人了
{new Node(1, 5), new Node(2, 7), new Node(6, 2)},//A
{new Node(0, 5), new Node(3, 9), new Node(6, 3)},
{new Node(0, 7), new Node(4, 8)},
{new Node(1, 9), new Node(5, 4)},//D
{new Node(2, 8), new Node(5, 5), new Node(6, 4)},
{new Node(3, 4), new Node(4, 5), new Node(6, 6)},//F
{new Node(0, 2), new Node(1, 3), new Node(4, 4), new Node(5, 6)}
};
for (int i = 0; i < data.length; i++) {
graph.add(data[i]);
for (int j = 0; j < edges[i].length; j++) {
graph.insertEdge(i, edges[i][j].sub, edges[i][j].weight);
}
}
graph.dsf(0);
Graph prim = graph.prim(0);
prim.dsf(0);
System.out.println(prim);
}
}
class Graph {
int E;//当前边数
int N;//顶点数量
int V;//当前顶点数量
ArrayList<Node>[] edges;
char[] data;//顶点数据,之前用的list存的,因为想着没法数组没法确认大小,但是我忘记了可以从构造器里面确定数组大小
private int[] check;
//构造器方法,将要用到的属性和容器初始化
public Graph(int N) {
this.N = N;
V = 0;
data = new char[N];
edges = new ArrayList[N];
check = new int[N];
for (int i = 0; i < N; i++) {
edges[i] = new ArrayList<>();
}
}
//prim算法生成mst入口方法
public Graph prim(int start) {
Graph graph = new Graph(N);
check[start] = 1;
while (graph.E < N - 1) {//线的个数比顶点数少1,即N-1条线
minOfPartGraph(graph);
}
check = new int[N];//用一次,还原一次,不然别的方法要用就会出错。
return graph;
}
//找到局部图所连接的,权值最小的路径,然后将该路径添加入局部图中
//调用一次,增长1个点以及点间最短的路径
//实现方法是遍历局部图中所有的点,让该点调用minOfPoint()方法,得到该点所连接的最短路径
//然后比较所有点返回的路径,得到一个最小路径,然后把路径添加入局部图中。
//注意:数值传递时不要弄混,点的下标和权值一定要一一对应。
public void minOfPartGraph(Graph graph) {
//用于筛选用的属性
int m = N + 1;
int minSub = N + 1;
int minWeight = Integer.MAX_VALUE;
//遍历局部图与整体图相交的点,并找出路径权值最低的那个点
//将两点间的线加入局部图中,让局部图增长
for (int i = 0; i < check.length; i++) {
if (check[i] == 1) {
Node node = minOfPoint(i);
if (node != null) {
int weight = node.weight;
if (minWeight > weight) {
minSub = node.sub;
minWeight = weight;
m = i;
}
}
}
}
check[minSub] = 1;
graph.insertEdge(m, minSub, minWeight);
}
//找到该点连接着的,最小的路径的点,然后将该点的信息返回(顶点的下标和权值)
//实现原理:遍历该点所连接的路径,从中挑选出一条最短的路径,然后返回该路径的信息
//注意:遍历该点所连接点,必须是未到达过的(避免成环)
public Node minOfPoint(int start) {
ArrayList<Node> edge = edges[start];
//应当做一些空及边界判断的事情,但是我这个是原型,就不搞了先
int minWeight = Integer.MAX_VALUE;
int minSub = N + 1;
boolean flag = false;
for (Node node : edge) {
//要从这个node里面取出一个最小的weight
//但是有个限定,即该点是未到达过的//如果这个点是到达过的,那么可能会添加重复的边,可能会形成环
int sub = node.sub;
if (check[sub] == 0) {
flag = true;
int weight = node.weight;
if (weight < minWeight) {
minWeight = weight;
minSub = sub;
}
}
}
if (flag) {
return new Node(minSub, minWeight);
} else return null;
}
public void dsf(int i) {
list_DFS(i);
check = new int[N];
}
private void list_DFS(int i) {
if (check[i] == 0) System.out.println("到达世界第" + i + "城," + data[i] + "城!");
check[i] = 1;
ArrayList<Node> list = edges[i];
for (Node node : list) {
if (check[node.sub] == 0) {
list_DFS(node.sub);
}
}
}
public void insertEdge(int m, int n, int weight) {
for (int i = 0; i < edges[m].size(); i++) {//解决重复添加问题
if (edges[m].get(i).sub == n && edges[m].get(i).weight == weight) {
return;
}
}
edges[m].add(new Node(n, weight));
edges[n].add(new Node(m, weight));
E++;
}
public void add(char c) {
data[V] = c;
V++;
}
}
class Node {
int sub;
int weight;
public Node(int sub, int weight) {
this.sub = sub;
this.weight = weight;
}
}
算法基础|prim算法的实现
最新推荐文章于 2024-09-25 13:54:13 发布
该代码示例展示了如何在Java中实现Prim算法来找到图的最小生成树。程序首先定义了一个图类,包含顶点、边和权重等属性,并提供了添加顶点、插入边的方法。接着,通过prim()方法逐步构建最小生成树,通过遍历和比较所有边的权重来选择最小的边加入到当前的树中。最后,使用深度优先搜索(DFS)展示生成的树。
摘要由CSDN通过智能技术生成