java: Prim Algorithms and Kruskal Algorithms
项目结构:

/**
* encoding: utf-8
* 版权所有 2026 ©涂聚文有限公司 ®
* 许可信息查看:言語成了邀功盡責的功臣,還需要行爲每日來值班嗎
* 描述:Prim Algorithms and Kruskal Algorithms 普里姆算法和克鲁斯卡尔算法
* Author : geovindu,Geovin Du 涂聚文.
* IDE : IntelliJ IDEA 2024.3.6 Java 21
* # database : Oracle21c,MySQL 9.0,SQL Server 2019,PostgreSQL 17.1 Neo4j
* # OS : window10
* Datetime : 2026 - 2026/8/8 - 6:52
* User : geovindu
* Product : IntelliJ IDEA
* Project : javadesginpattern
* File : AggregateRoot.java
* explain : 学习 类
**/
package PrimKruskal.common;
import java.util.ArrayList;
import java.util.List;
/**
* DDD聚合根顶层抽象类
*/
public abstract class AggregateRoot {
private final List<Object> domainEvents = new ArrayList<>();
public List<Object> getDomainEvents() {
return new ArrayList<>(domainEvents);
}
public void clearDomainEvents() {
domainEvents.clear();
}
}
/**
* encoding: utf-8
* 版权所有 2026 ©涂聚文有限公司 ®
* 许可信息查看:言語成了邀功盡責的功臣,還需要行爲每日來值班嗎
* 描述:Prim Algorithms and Kruskal Algorithms 普里姆算法和克鲁斯卡尔算法
* Author : geovindu,Geovin Du 涂聚文.
* IDE : IntelliJ IDEA 2024.3.6 Java 21
* # database : Oracle21c,MySQL 9.0,SQL Server 2019,PostgreSQL 17.1 Neo4j
* # OS : window10
* Datetime : 2026 - 2026/8/8 - 6:53
* User : geovindu
* Product : IntelliJ IDEA
* Project : javadesginpattern
* File : DomainException.java
* explain : 学习 类
**/
package PrimKruskal.common;
/**
* 统一领域业务异常
*/
public class DomainException extends RuntimeException {
public DomainException(String message) {
super("【领域异常】" + message);
}
}
/**
* encoding: utf-8
* 版权所有 2026 ©涂聚文有限公司 ®
* 许可信息查看:言語成了邀功盡責的功臣,還需要行爲每日來值班嗎
* 描述:Prim Algorithms and Kruskal Algorithms 普里姆算法和克鲁斯卡尔算法
* Author : geovindu,Geovin Du 涂聚文.
* IDE : IntelliJ IDEA 2024.3.6 Java 21
* # database : Oracle21c,MySQL 9.0,SQL Server 2019,PostgreSQL 17.1 Neo4j
* # OS : window10
* Datetime : 2026 - 2026/8/8 - 6:53
* User : geovindu
* Product : IntelliJ IDEA
* Project : javadesginpattern
* File : Entity.java
* explain : 学习 类
**/
package PrimKruskal.common;
/**
* DDD实体基类:唯一ID标识
*/
public abstract class Entity {
private final int id;
protected Entity(int id) {
this.id = id;
}
public int getId() {
return id;
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
Entity entity = (Entity) o;
return id == entity.id;
}
@Override
public int hashCode() {
return id;
}
}
/**
* encoding: utf-8
* 版权所有 2026 ©涂聚文有限公司 ®
* 许可信息查看:言語成了邀功盡責的功臣,還需要行爲每日來值班嗎
* 描述:Prim Algorithms and Kruskal Algorithms 普里姆算法和克鲁斯卡尔算法
* Author : geovindu,Geovin Du 涂聚文.
* IDE : IntelliJ IDEA 2024.3.6 Java 21
* # database : Oracle21c,MySQL 9.0,SQL Server 2019,PostgreSQL 17.1 Neo4j
* # OS : window10
* Datetime : 2026 - 2026/8/8 - 6:53
* User : geovindu
* Product : IntelliJ IDEA
* Project : javadesginpattern
* File : IValueObject.java
* explain : 学习 类
**/
package PrimKruskal.common;
/**
* DDD值对象接口:不可变,基于属性判等
*/
public interface IValueObject {
boolean equals(IValueObject other);
}
/**
* encoding: utf-8
* 版权所有 2026 ©涂聚文有限公司 ®
* 许可信息查看:言語成了邀功盡責的功臣,還需要行爲每日來值班嗎
* 描述:Prim Algorithms and Kruskal Algorithms 普里姆算法和克鲁斯卡尔算法
* Author : geovindu,Geovin Du 涂聚文.
* IDE : IntelliJ IDEA 2024.3.6 Java 21
* # database : Oracle21c,MySQL 9.0,SQL Server 2019,PostgreSQL 17.1 Neo4j
* # OS : window10
* Datetime : 2026 - 2026/8/8 - 6:54
* User : geovindu
* Product : IntelliJ IDEA
* Project : javadesginpattern
* File : UnionFind.java
* explain : 学习 类
**/
package PrimKruskal.common;
/**
* 并查集,Kruskal算法依赖,带路径压缩
*/
public class UnionFind {
private int[] parent;
public UnionFind(int size) {
parent = new int[size];
for (int i = 0; i < size; i++) {
parent[i] = i;
}
}
/**
* 查找根节点+路径压缩
*/
public int find(int x) {
if (parent[x] != x) {
parent[x] = find(parent[x]);
}
return parent[x];
}
/**
* 合并两个集合
* @return true合并成功无环,false成环
*/
public boolean union(int x, int y) {
int rootX = find(x);
int rootY = find(y);
if (rootX == rootY) {
return false;
}
parent[rootY] = rootX;
return true;
}
}
/**
* encoding: utf-8
* 版权所有 2026 ©涂聚文有限公司 ®
* 许可信息查看:言語成了邀功盡責的功臣,還需要行爲每日來值班嗎
* 描述:Prim Algorithms and Kruskal Algorithms 普里姆算法和克鲁斯卡尔算法
* Author : geovindu,Geovin Du 涂聚文.
* IDE : IntelliJ IDEA 2024.3.6 Java 21
* # database : Oracle21c,MySQL 9.0,SQL Server 2019,PostgreSQL 17.1 Neo4j
* # OS : window10
* Datetime : 2026 - 2026/8/8 - 6:57
* User : geovindu
* Product : IntelliJ IDEA
* Project : javadesginpattern
* File : KruskalAlgorithm.java
* explain : 学习 类
**/
package PrimKruskal.domain.algorithm;
import PrimKruskal.common.DomainException;
import PrimKruskal.common.UnionFind;
import PrimKruskal.domain.model.LogisticsEdge;
import PrimKruskal.domain.model.LogisticsNode;
import java.util.ArrayList;
import java.util.List;
import java.util.stream.Collectors;
/**
* Kruskal最小生成树领域算法服务
* 适用:跨城分散矿区、门店【稀疏图】
*/
public class KruskalAlgorithm {
public static Result calculate(List<LogisticsEdge> edgeList, List<LogisticsNode> nodes) {
int nodeCnt = nodes.size();
if (nodeCnt <= 0) {
throw new DomainException("网点集合不能为空,无法生成物流路网");
}
// 按成本升序排序
List<LogisticsEdge> sortedEdges = edgeList.stream()
.sorted((e1, e2) -> Double.compare(e1.getCost(), e2.getCost()))
.collect(Collectors.toList());
UnionFind uf = new UnionFind(nodeCnt);
List<LogisticsEdge> mstEdges = new ArrayList<>();
double totalCost = 0D;
for (LogisticsEdge edge : sortedEdges) {
if (uf.union(edge.getStartId(), edge.getEndId())) {
mstEdges.add(edge);
totalCost += edge.getCost();
if (mstEdges.size() == nodeCnt - 1) {
break;
}
}
}
if (mstEdges.size() != nodeCnt - 1) {
throw new DomainException("网点图不连通,无法构建完整物流最小生成树");
}
return new Result(mstEdges, totalCost);
}
public static class Result {
private final List<LogisticsEdge> edges;
private final double cost;
public Result(List<LogisticsEdge> edges, double cost) {
this.edges = edges;
this.cost = cost;
}
public List<LogisticsEdge> getEdges() {
return edges;
}
public double getCost() {
return cost;
}
}
}
/**
* encoding: utf-8
* 版权所有 2026 ©涂聚文有限公司 ®
* 许可信息查看:言語成了邀功盡責的功臣,還需要行爲每日來值班嗎
* 描述:Prim Algorithms and Kruskal Algorithms 普里姆算法和克鲁斯卡尔算法
* Author : geovindu,Geovin Du 涂聚文.
* IDE : IntelliJ IDEA 2024.3.6 Java 21
* # database : Oracle21c,MySQL 9.0,SQL Server 2019,PostgreSQL 17.1 Neo4j
* # OS : window10
* Datetime : 2026 - 2026/8/8 - 6:56
* User : geovindu
* Product : IntelliJ IDEA
* Project : javadesginpattern
* File : PrimAlgorithm.java
* explain : 学习 类
**/
package PrimKruskal.domain.algorithm;
import PrimKruskal.common.DomainException;
import PrimKruskal.domain.model.LogisticsEdge;
import PrimKruskal.domain.model.LogisticsNode;
import java.util.ArrayList;
import java.util.List;
/**
* Prim最小生成树领域算法服务
* 适用:商圈门店、加工厂密集【稠密图】
*/
public class PrimAlgorithm {
public static Result calculate(double[][] adjMatrix, List<LogisticsNode> nodes) {
int nodeCnt = nodes.size();
if (nodeCnt <= 0) {
throw new DomainException("网点集合不能为空,无法生成物流路网");
}
final double INF = Double.MAX_VALUE;
boolean[] inMst = new boolean[nodeCnt];
double[] minDist = new double[nodeCnt];
int[] preNode = new int[nodeCnt];
for (int i = 0; i < nodeCnt; i++) {
minDist[i] = INF;
preNode[i] = -1;
}
minDist[0] = 0;
List<LogisticsEdge> edgeList = new ArrayList<>();
double totalCost = 0D;
for (int round = 0; round < nodeCnt; round++) {
// 选取距离生成树最近的未加入节点
int selectIdx = -1;
double minVal = INF;
for (int i = 0; i < nodeCnt; i++) {
if (!inMst[i] && minDist[i] < minVal) {
minVal = minDist[i];
selectIdx = i;
}
}
if (selectIdx == -1) {
throw new DomainException("网点图不连通,无法构建完整物流最小生成树");
}
inMst[selectIdx] = true;
totalCost += minVal;
// 记录边
int preIdx = preNode[selectIdx];
if (preIdx != -1) {
edgeList.add(new LogisticsEdge(preIdx, selectIdx, adjMatrix[preIdx][selectIdx]));
}
// 松弛更新邻接点距离
for (int j = 0; j < nodeCnt; j++) {
double weight = adjMatrix[selectIdx][j];
if (!inMst[j] && weight > 0 && weight < minDist[j]) {
minDist[j] = weight;
preNode[j] = selectIdx;
}
}
}
return new Result(edgeList, totalCost);
}
/** 算法返回结果封装 */
public static class Result {
private final List<LogisticsEdge> edges;
private final double cost;
public Result(List<LogisticsEdge> edges, double cost) {
this.edges = edges;
this.cost = cost;
}
public List<LogisticsEdge> getEdges() {
return edges;
}
public double getCost() {
return cost;
}
}
}
/**
* encoding: utf-8
* 版权所有 2026 ©涂聚文有限公司 ®
* 许可信息查看:言語成了邀功盡責的功臣,還需要行爲每日來值班嗎
* 描述:Prim Algorithms and Kruskal Algorithms 普里姆算法和克鲁斯卡尔算法
* Author : geovindu,Geovin Du 涂聚文.
* IDE : IntelliJ IDEA 2024.3.6 Java 21
* # database : Oracle21c,MySQL 9.0,SQL Server 2019,PostgreSQL 17.1 Neo4j
* # OS : window10
* Datetime : 2026 - 2026/8/8 - 6:55
* User : geovindu
* Product : IntelliJ IDEA
* Project : javadesginpattern
* File : LogisticsEdge.java
* explain : 学习 类
**/
package PrimKruskal.domain.model;
import PrimKruskal.common.IValueObject;
/**
* 运输线路【值对象】
* cost:综合成本(路费、押运安保、保险、货品损耗),单位千元
*/
public class LogisticsEdge implements IValueObject {
private final int startId;
private final int endId;
private final double cost;
public LogisticsEdge(int startId, int endId, double cost) {
this.startId = startId;
this.endId = endId;
this.cost = cost;
}
public int getStartId() {
return startId;
}
public int getEndId() {
return endId;
}
public double getCost() {
return cost;
}
@Override
public boolean equals(IValueObject other) {
if (!(other instanceof LogisticsEdge)) {
return false;
}
LogisticsEdge edge = (LogisticsEdge) other;
return this.startId == edge.startId
&& this.endId == edge.endId
&& Double.compare(this.cost, edge.cost) == 0;
}
}
/**
* encoding: utf-8
* 版权所有 2026 ©涂聚文有限公司 ®
* 许可信息查看:言語成了邀功盡責的功臣,還需要行爲每日來值班嗎
* 描述:Prim Algorithms and Kruskal Algorithms 普里姆算法和克鲁斯卡尔算法
* Author : geovindu,Geovin Du 涂聚文.
* IDE : IntelliJ IDEA 2024.3.6 Java 21
* # database : Oracle21c,MySQL 9.0,SQL Server 2019,PostgreSQL 17.1 Neo4j
* # OS : window10
* Datetime : 2026 - 2026/8/8 - 6:56
* User : geovindu
* Product : IntelliJ IDEA
* Project : javadesginpattern
* File : LogisticsMST.java
* explain : 学习 类
**/
package PrimKruskal.domain.model;
import PrimKruskal.common.AggregateRoot;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
/**
* 最小生成树聚合根
* 聚合:全部网点、MST选中线路、全网总成本
*/
public class LogisticsMST extends AggregateRoot {
private List<LogisticsNode> allNodes = new ArrayList<>();
private List<LogisticsEdge> mstEdges = new ArrayList<>();
private double totalCost = 0D;
public void setAllNodes(List<LogisticsNode> allNodes) {
this.allNodes = allNodes;
}
public void setResult(List<LogisticsEdge> edges, double totalCost) {
this.mstEdges = edges;
this.totalCost = totalCost;
}
public double getTotalCost() {
return totalCost;
}
public List<LogisticsEdge> getMstEdges() {
return mstEdges;
}
/**
* 格式化打印详情,封装成 起点名、终点名、成本
*/
public List<Object[]> getDetailList() {
Map<Integer, String> nodeNameMap = new HashMap<>();
for (LogisticsNode node : allNodes) {
nodeNameMap.put(node.getId(), node.getNodeName());
}
List<Object[]> result = new ArrayList<>();
for (LogisticsEdge edge : mstEdges) {
String sName = nodeNameMap.get(edge.getStartId());
String eName = nodeNameMap.get(edge.getEndId());
result.add(new Object[]{sName, eName, edge.getCost()});
}
return result;
}
}
/**
* encoding: utf-8
* 版权所有 2026 ©涂聚文有限公司 ®
* 许可信息查看:言語成了邀功盡責的功臣,還需要行爲每日來值班嗎
* 描述:Prim Algorithms and Kruskal Algorithms 普里姆算法和克鲁斯卡尔算法
* Author : geovindu,Geovin Du 涂聚文.
* IDE : IntelliJ IDEA 2024.3.6 Java 21
* # database : Oracle21c,MySQL 9.0,SQL Server 2019,PostgreSQL 17.1 Neo4j
* # OS : window10
* Datetime : 2026 - 2026/8/8 - 6:54
* User : geovindu
* Product : IntelliJ IDEA
* Project : javadesginpattern
* File : LogisticsNode.java
* explain : 学习 类
**/
package PrimKruskal.domain.model;
import PrimKruskal.common.Entity;
/**
* 物流网点【实体】
* 珠宝供应链节点:矿区、加工厂、仓储、线下门店
*/
public class LogisticsNode extends Entity {
private final String nodeName;
private final String nodeCategory;
public LogisticsNode(int id, String nodeName, String nodeCategory) {
super(id);
this.nodeName = nodeName;
this.nodeCategory = nodeCategory;
}
public String getNodeName() {
return nodeName;
}
public String getNodeCategory() {
return nodeCategory;
}
}
调用:
/**
* encoding: utf-8
* 版权所有 2026 ©涂聚文有限公司 ®
* 许可信息查看:言語成了邀功盡責的功臣,還需要行爲每日來值班嗎
* 描述:Prim Algorithms and Kruskal Algorithms 普里姆算法和克鲁斯卡尔算法
* Author : geovindu,Geovin Du 涂聚文.
* IDE : IntelliJ IDEA 2024.3.6 Java 21
* # database : Oracle21c,MySQL 9.0,SQL Server 2019,PostgreSQL 17.1 Neo4j
* # OS : window10
* Datetime : 2026 - 2026/8/8 - 7:01
* User : geovindu
* Product : IntelliJ IDEA
* Project : javadesginpattern
* File : PrimKruskalBll.java
* explain : 学习 类
**/
package Bll;
import PrimKruskal.application.LogisticsRouteAppService;
import PrimKruskal.domain.model.LogisticsEdge;
import PrimKruskal.domain.model.LogisticsMST;
import PrimKruskal.domain.model.LogisticsNode;
import java.util.ArrayList;
import java.util.List;
public class PrimKruskalBll {
/**
* 示例
*/
public void Demo()
{
// 1. 初始化珠宝供应链网点
List<LogisticsNode> nodeList = new ArrayList<>();
nodeList.add(new LogisticsNode(0, "缅甸翡翠矿区A", "原料矿区"));
nodeList.add(new LogisticsNode(1, "云南分拣加工厂", "加工中心"));
nodeList.add(new LogisticsNode(2, "深圳总仓储中心", "仓储中心"));
nodeList.add(new LogisticsNode(3, "广州旗舰门店", "线下门店"));
nodeList.add(new LogisticsNode(4, "上海门店", "线下门店"));
nodeList.add(new LogisticsNode(5, "北京门店", "线下门店"));
// 2. Prim邻接矩阵,0=无直达路线
double[][] adjMatrix = {
{0, 12, 28, 0, 0, 0},
{12, 0, 8, 15, 0, 0},
{28, 8, 0, 6, 18, 22},
{0, 15, 6, 0, 25, 0},
{0, 0, 18, 25, 0, 14},
{0, 0, 22, 0, 14, 0}
};
// 3. Kruskal原始边集合
List<LogisticsEdge> edgeList = new ArrayList<>();
edgeList.add(new LogisticsEdge(0, 1, 12));
edgeList.add(new LogisticsEdge(0, 2, 28));
edgeList.add(new LogisticsEdge(1, 2, 8));
edgeList.add(new LogisticsEdge(1, 3, 15));
edgeList.add(new LogisticsEdge(2, 3, 6));
edgeList.add(new LogisticsEdge(2, 4, 18));
edgeList.add(new LogisticsEdge(2, 5, 22));
edgeList.add(new LogisticsEdge(3, 4, 25));
edgeList.add(new LogisticsEdge(4, 5, 14));
LogisticsRouteAppService appService = new LogisticsRouteAppService();
// Prim输出
System.out.println("========== Prim算法-稠密网点物流规划 ==========");
LogisticsMST primMst = appService.buildByPrim(adjMatrix, nodeList);
for (Object[] item : primMst.getDetailList()) {
String start = (String) item[0];
String end = (String) item[1];
double cost = (Double) item[2];
System.out.printf("%s <--> %s 运输成本:%.0f千元%n", start, end, cost);
}
System.out.printf("全网最低总成本:%.0f 千元%n%n", primMst.getTotalCost());
// Kruskal输出
System.out.println("========== Kruskal算法-稀疏跨城网点规划 ==========");
LogisticsMST krusMst = appService.buildByKruskal(edgeList, nodeList);
for (Object[] item : krusMst.getDetailList()) {
String start = (String) item[0];
String end = (String) item[1];
double cost = (Double) item[2];
System.out.printf("%s <--> %s 运输成本:%.0f千元%n", start, end, cost);
}
System.out.printf("全网最低总成本:%.0f 千元%n", krusMst.getTotalCost());
}
}
哲学管理(学)人生, 文学艺术生活, 自动(计算机学)物理(学)工作, 生物(学)化学逆境, 历史(学)测绘(学)时间, 经济(学)数学金钱(理财), 心理(学)医学情绪, 诗词美容情感, 美学建筑(学)家园, 解构建构(分析)整合学习, 智商情商(IQ、EQ)运筹(学)生存.---Geovin Du(涂聚文)
浙公网安备 33010602011771号