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

/*
# encoding: utf-8
# 版权所有 2026 ©涂聚文有限公司™ ®
# 许可信息查看:言語成了邀功盡責的功臣,還需要行爲每日來值班嗎
# 描述:Prim Algorithms and Kruskal Algorithms 普里姆算法和克鲁斯卡尔算法
# Author : geovindu,Geovin Du 涂聚文.
# IDE : vs2026 c# .net 10
# os : windows 10
# database : mysql 9.0 sql server 2019, postgreSQL 17.0 Oracle 21c Neo4j
# Datetime : 2026/08/01 22:16
# User : geovindu
# Product : Visual Studio 2026
# Project : CSharpDesignPattern
# File : AggregateRoot.cs
*/
using System;
using System.Collections.Generic;
using System.Text;
namespace CSharpAlgorithms.PrimKruskal.Common
{
/// <summary>
/// DDD 聚合根顶层基类
/// </summary>
public abstract class AggregateRoot
{
private readonly List<object> _domainEvents = new List<object>();
public List<object> GetDomainEvents()
{
return new List<object>(_domainEvents);
}
public void ClearDomainEvents()
{
_domainEvents.Clear();
}
}
}
/*
# encoding: utf-8
# 版权所有 2026 ©涂聚文有限公司™ ®
# 许可信息查看:言語成了邀功盡責的功臣,還需要行爲每日來值班嗎
# 描述:Prim Algorithms and Kruskal Algorithms 普里姆算法和克鲁斯卡尔算法
# Author : geovindu,Geovin Du 涂聚文.
# IDE : vs2026 c# .net 10
# os : windows 10
# database : mysql 9.0 sql server 2019, postgreSQL 17.0 Oracle 21c Neo4j
# Datetime : 2026/08/01 22:16
# User : geovindu
# Product : Visual Studio 2026
# Project : CSharpDesignPattern
# File : Entity.cs
*/
using System;
using System.Collections.Generic;
using System.Text;
namespace CSharpAlgorithms.PrimKruskal.Common
{
/// <summary>
/// DDD 实体基类:拥有唯一Id标识
/// </summary>
public abstract class Entity
{
private readonly int _id;
protected Entity(int id)
{
_id = id;
}
public int Id => _id;
public override bool Equals(object obj)
{
return obj is Entity entity && Id == entity.Id;
}
public override int GetHashCode()
{
return Id;
}
}
}
/*
# encoding: utf-8
# 版权所有 2026 ©涂聚文有限公司™ ®
# 许可信息查看:言語成了邀功盡責的功臣,還需要行爲每日來值班嗎
# 描述:Prim Algorithms and Kruskal Algorithms 普里姆算法和克鲁斯卡尔算法
# Author : geovindu,Geovin Du 涂聚文.
# IDE : vs2026 c# .net 10
# os : windows 10
# database : mysql 9.0 sql server 2019, postgreSQL 17.0 Oracle 21c Neo4j
# Datetime : 2026/08/01 22:16
# User : geovindu
# Product : Visual Studio 2026
# Project : CSharpDesignPattern
# File : IValueObject.cs
*/
using System;
using System.Collections.Generic;
using System.Text;
namespace CSharpAlgorithms.PrimKruskal.Common
{
/// <summary>
/// DDD 值对象:不可变,基于属性判等
/// </summary>
public interface IValueObject
{
bool Equals(IValueObject other);
}
}
/*
# encoding: utf-8
# 版权所有 2026 ©涂聚文有限公司™ ®
# 许可信息查看:言語成了邀功盡責的功臣,還需要行爲每日來值班嗎
# 描述:Prim Algorithms and Kruskal Algorithms 普里姆算法和克鲁斯卡尔算法
# Author : geovindu,Geovin Du 涂聚文.
# IDE : vs2026 c# .net 10
# os : windows 10
# database : mysql 9.0 sql server 2019, postgreSQL 17.0 Oracle 21c Neo4j
# Datetime : 2026/08/01 22:16
# User : geovindu
# Product : Visual Studio 2026
# Project : CSharpDesignPattern
# File : DomainException.cs
*/
using System;
using System.Collections.Generic;
using System.Text;
namespace CSharpAlgorithms.PrimKruskal.Common
{
/// <summary>
/// 全局领域业务异常
/// </summary>
public class DomainException : Exception
{
public DomainException(string message) : base($"【领域异常】{message}")
{
}
}
}
/*
# encoding: utf-8
# 版权所有 2026 ©涂聚文有限公司™ ®
# 许可信息查看:言語成了邀功盡責的功臣,還需要行爲每日來值班嗎
# 描述:Prim Algorithms and Kruskal Algorithms 普里姆算法和克鲁斯卡尔算法
# Author : geovindu,Geovin Du 涂聚文.
# IDE : vs2026 c# .net 10
# os : windows 10
# database : mysql 9.0 sql server 2019, postgreSQL 17.0 Oracle 21c Neo4j
# Datetime : 2026/08/01 22:16
# User : geovindu
# Product : Visual Studio 2026
# Project : CSharpDesignPattern
# File : UnionFind.cs
*/
using System;
using System.Collections.Generic;
using System.Text;
namespace CSharpAlgorithms.PrimKruskal.Common
{
/// <summary>
/// 并查集:Kruskal算法依赖,路径压缩
/// </summary>
public class UnionFind
{
private readonly int[] _parent;
public UnionFind(int size)
{
_parent = new int[size];
for (int i = 0; i < size; i++)
{
_parent[i] = i;
}
}
/// <summary>
/// 查找根节点+路径压缩
/// </summary>
public int Find(int x)
{
if (_parent[x] != x)
{
_parent[x] = Find(_parent[x]);
}
return _parent[x];
}
/// <summary>
/// 合并集合
/// 返回true:无环合并成功;false:同集合成环
/// </summary>
public bool 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 : vs2026 c# .net 10
# os : windows 10
# database : mysql 9.0 sql server 2019, postgreSQL 17.0 Oracle 21c Neo4j
# Datetime : 2026/08/01 22:16
# User : geovindu
# Product : Visual Studio 2026
# Project : CSharpDesignPattern
# File : LogisticsNode.cs
*/
using CSharpAlgorithms.PrimKruskal.Common;
using System;
using System.Collections.Generic;
using System.Text;
namespace CSharpAlgorithms.PrimKruskal.Domain.Model
{
/// <summary>
/// 物流网点【实体】
/// 珠宝供应链节点:矿区、加工厂、仓库、线下门店
/// </summary>
public class LogisticsNode : Entity
{
/// <summary>网点名称</summary>
public string NodeName { get; }
/// <summary>网点分类:原料矿区/加工中心/仓储中心/线下门店</summary>
public string NodeCategory { get; }
public LogisticsNode(int id, string nodeName, string nodeCategory) : base(id)
{
NodeName = nodeName;
NodeCategory = nodeCategory;
}
}
}
/*
# encoding: utf-8
# 版权所有 2026 ©涂聚文有限公司™ ®
# 许可信息查看:言語成了邀功盡責的功臣,還需要行爲每日來值班嗎
# 描述:Prim Algorithms and Kruskal Algorithms 普里姆算法和克鲁斯卡尔算法
# Author : geovindu,Geovin Du 涂聚文.
# IDE : vs2026 c# .net 10
# os : windows 10
# database : mysql 9.0 sql server 2019, postgreSQL 17.0 Oracle 21c Neo4j
# Datetime : 2026/08/01 22:16
# User : geovindu
# Product : Visual Studio 2026
# Project : CSharpDesignPattern
# File : LogisticsEdge.cs
*/
using CSharpAlgorithms.PrimKruskal.Common;
using System;
using System.Collections.Generic;
using System.Text;
namespace CSharpAlgorithms.PrimKruskal.Domain.Model
{
/// <summary>
/// 物流运输线路【值对象】
/// 权重:综合运输成本(路费、押运、保险、货品损耗),单位:千元
/// </summary>
public class LogisticsEdge : IValueObject
{
public int StartId { get; }
public int EndId { get; }
public double Cost { get; }
public LogisticsEdge(int startId, int endId, double cost)
{
StartId = startId;
EndId = endId;
Cost = cost;
}
public bool Equals(IValueObject other)
{
if (!(other is LogisticsEdge edge))
return false;
return StartId == edge.StartId && EndId == edge.EndId && Cost == edge.Cost;
}
}
}
/*
# encoding: utf-8
# 版权所有 2026 ©涂聚文有限公司™ ®
# 许可信息查看:言語成了邀功盡責的功臣,還需要行爲每日來值班嗎
# 描述:Prim Algorithms and Kruskal Algorithms 普里姆算法和克鲁斯卡尔算法
# Author : geovindu,Geovin Du 涂聚文.
# IDE : vs2026 c# .net 10
# os : windows 10
# database : mysql 9.0 sql server 2019, postgreSQL 17.0 Oracle 21c Neo4j
# Datetime : 2026/08/01 22:16
# User : geovindu
# Product : Visual Studio 2026
# Project : CSharpDesignPattern
# File : LogisticsMST.cs
*/
using CSharpAlgorithms.PrimKruskal.Common;
using System;
using System.Collections.Generic;
using System.Text;
namespace CSharpAlgorithms.PrimKruskal.Domain.Model
{
/// <summary>
/// 最小生成树【聚合根】
/// 聚合:所有网点、MST选中线路、全网总成本
/// </summary>
public class LogisticsMST : AggregateRoot
{
public List<LogisticsNode> AllNodes { get; set; } = new List<LogisticsNode>();
public List<LogisticsEdge> MstEdges { get; set; } = new List<LogisticsEdge>();
public double TotalCost { get; set; }
public void SetNodes(List<LogisticsNode> nodes)
{
AllNodes = nodes;
}
public void SetResult(List<LogisticsEdge> edges, double totalCost)
{
MstEdges = edges;
TotalCost = totalCost;
}
/// <summary>
/// 格式化线路详情,用于控制台打印输出
/// </summary>
public List<Tuple<string, string, double>> GetDetailList()
{
Dictionary<int, string> nameMap = new Dictionary<int, string>();
foreach (var node in AllNodes)
{
nameMap[node.Id] = node.NodeName;
}
List<Tuple<string, string, double>> list = new List<Tuple<string, string, double>>();
foreach (var edge in MstEdges)
{
list.Add(Tuple.Create(nameMap[edge.StartId], nameMap[edge.EndId], edge.Cost));
}
return list;
}
}
}
/*
# encoding: utf-8
# 版权所有 2026 ©涂聚文有限公司™ ®
# 许可信息查看:言語成了邀功盡責的功臣,還需要行爲每日來值班嗎
# 描述:Prim Algorithms and Kruskal Algorithms 普里姆算法和克鲁斯卡尔算法
# Author : geovindu,Geovin Du 涂聚文.
# IDE : vs2026 c# .net 10
# os : windows 10
# database : mysql 9.0 sql server 2019, postgreSQL 17.0 Oracle 21c Neo4j
# Datetime : 2026/08/01 22:16
# User : geovindu
# Product : Visual Studio 2026
# Project : CSharpDesignPattern
# File : PrimAlgorithm.cs
*/
using CSharpAlgorithms.PrimKruskal.Common;
using CSharpAlgorithms.PrimKruskal.Domain.Model;
using System;
using System.Collections.Generic;
using System.Text;
namespace CSharpAlgorithms.PrimKruskal.Domain.Algorithm
{
/// <summary>
/// Prim最小生成树 领域算法服务
/// 适用场景:门店、加工厂密集稠密图
/// </summary>
public static class PrimAlgorithm
{
public static Tuple<List<LogisticsEdge>, double> Calculate(double[][] adjMatrix, List<LogisticsNode> nodes)
{
int nodeCount = nodes.Count;
if (nodeCount <= 0)
throw new DomainException("网点集合不能为空,无法生成物流路网");
double INF = double.MaxValue;
bool[] inMst = new bool[nodeCount];
double[] minDist = new double[nodeCount];
int[] preNode = new int[nodeCount];
for (int i = 0; i < nodeCount; i++)
{
minDist[i] = INF;
preNode[i] = -1;
}
minDist[0] = 0;
double totalCost = 0;
List<LogisticsEdge> mstEdges = new List<LogisticsEdge>();
for (int round = 0; round < nodeCount; round++)
{
// 选取距离MST最近节点
int selectIdx = -1;
double minVal = INF;
for (int i = 0; i < nodeCount; 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)
{
mstEdges.Add(new LogisticsEdge(preIdx, selectIdx, adjMatrix[preIdx][selectIdx]));
}
// 松弛更新邻接点距离
for (int j = 0; j < nodeCount; j++)
{
double weight = adjMatrix[selectIdx][j];
if (!inMst[j] && weight > 0 && weight < minDist[j])
{
minDist[j] = weight;
preNode[j] = selectIdx;
}
}
}
return Tuple.Create(mstEdges, totalCost);
}
}
}
/*
# encoding: utf-8
# 版权所有 2026 ©涂聚文有限公司™ ®
# 许可信息查看:言語成了邀功盡責的功臣,還需要行爲每日來值班嗎
# 描述:Prim Algorithms and Kruskal Algorithms 普里姆算法和克鲁斯卡尔算法
# Author : geovindu,Geovin Du 涂聚文.
# IDE : vs2026 c# .net 10
# os : windows 10
# database : mysql 9.0 sql server 2019, postgreSQL 17.0 Oracle 21c Neo4j
# Datetime : 2026/08/01 22:16
# User : geovindu
# Product : Visual Studio 2026
# Project : CSharpDesignPattern
# File : KruskalAlgorithm.cs
*/
using CSharpAlgorithms.PrimKruskal.Common;
using CSharpAlgorithms.PrimKruskal.Domain.Model;
using System;
using System.Collections.Generic;
using System.Text;
namespace CSharpAlgorithms.PrimKruskal.Domain.Algorithm
{
/// <summary>
/// Kruskal最小生成树 领域算法服务
/// 适用场景:跨城分散网点稀疏图
/// </summary>
public static class KruskalAlgorithm
{
public static Tuple<List<LogisticsEdge>, double> Calculate(List<LogisticsEdge> edgeList, List<LogisticsNode> nodes)
{
int nodeCount = nodes.Count;
if (nodeCount <= 0)
throw new DomainException("网点集合不能为空,无法生成物流路网");
// 边按成本升序排序
var sortedEdges = edgeList.OrderBy(e => e.Cost).ToList();
UnionFind uf = new UnionFind(nodeCount);
List<LogisticsEdge> mstEdges = new List<LogisticsEdge>();
double totalCost = 0;
foreach (var edge in sortedEdges)
{
if (uf.Union(edge.StartId, edge.EndId))
{
mstEdges.Add(edge);
totalCost += edge.Cost;
if (mstEdges.Count == nodeCount - 1)
break;
}
}
if (mstEdges.Count != nodeCount - 1)
throw new DomainException("网点图不连通,无法构建完整物流最小生成树");
return Tuple.Create(mstEdges, totalCost);
}
}
}
/*
# encoding: utf-8
# 版权所有 2026 ©涂聚文有限公司™ ®
# 许可信息查看:言語成了邀功盡責的功臣,還需要行爲每日來值班嗎
# 描述:Prim Algorithms and Kruskal Algorithms 普里姆算法和克鲁斯卡尔算法
# Author : geovindu,Geovin Du 涂聚文.
# IDE : vs2026 c# .net 10
# os : windows 10
# database : mysql 9.0 sql server 2019, postgreSQL 17.0 Oracle 21c Neo4j
# Datetime : 2026/08/01 22:16
# User : geovindu
# Product : Visual Studio 2026
# Project : CSharpDesignPattern
# File : LogisticsRouteAppService.cs
*/
using CSharpAlgorithms.PrimKruskal.Domain.Algorithm;
using CSharpAlgorithms.PrimKruskal.Domain.Model;
using System;
using System.Collections.Generic;
using System.Text;
namespace CSharpAlgorithms.PrimKruskal.Application
{
/// <summary>
/// 物流路线应用服务:只做编排调度,不写核心算法
/// </summary>
public class LogisticsRouteAppService
{
/// <summary>
/// Prim生成最小生成树
/// </summary>
public LogisticsMST BuildByPrim(double[][] adjMatrix, List<LogisticsNode> nodes)
{
var res = PrimAlgorithm.Calculate(adjMatrix, nodes);
LogisticsMST mst = new LogisticsMST();
mst.SetNodes(nodes);
mst.SetResult(res.Item1, res.Item2);
return mst;
}
/// <summary>
/// Kruskal生成最小生成树
/// </summary>
public LogisticsMST BuildByKruskal(List<LogisticsEdge> edges, List<LogisticsNode> nodes)
{
var res = KruskalAlgorithm.Calculate(edges, nodes);
LogisticsMST mst = new LogisticsMST();
mst.SetNodes(nodes);
mst.SetResult(res.Item1, res.Item2);
return mst;
}
}
}
调用:
/*
# encoding: utf-8
# 版权所有 2026 ©涂聚文有限公司™ ®
# 许可信息查看:言語成了邀功盡責的功臣,還需要行爲每日來值班嗎
# 描述:Prim Algorithms and Kruskal Algorithms 普里姆算法和克鲁斯卡尔算法
# Author : geovindu,Geovin Du 涂聚文.
# IDE : vs2026 c# .net 10
# os : windows 10
# database : mysql 9.0 sql server 2019, postgreSQL 17.0 Oracle 21c Neo4j
# Datetime : 2026/08/01 22:16
# User : geovindu
# Product : Visual Studio 2026
# Project : CSharpDesignPattern
# File : PrimKruskalBll.cs
*/
using System;
using System.Collections.Generic;
using System.Text;
using CSharpAlgorithms.PrimKruskal.Application;
using CSharpAlgorithms.PrimKruskal.Domain.Model;
namespace CSharpAlgorithms.Bll
{
/// <summary>
///
/// </summary>
public class PrimKruskalBll
{
public void Demo()
{
// 1、初始化珠宝供应链网点
List<LogisticsNode> nodeList = new List<LogisticsNode>()
{
new LogisticsNode(0,"缅甸翡翠矿区A","原料矿区"),
new LogisticsNode(1,"云南分拣加工厂","加工中心"),
new LogisticsNode(2,"深圳总仓储中心","仓储中心"),
new LogisticsNode(3,"广州旗舰门店","线下门店"),
new LogisticsNode(4,"上海门店","线下门店"),
new LogisticsNode(5,"北京门店","线下门店")
};
// 2、Prim邻接矩阵,0代表无直达路线
double[][] adjMatrix = new double[][]
{
new double[]{0,12,28,0,0,0},
new double[]{12,0,8,15,0,0},
new double[]{28,8,0,6,18,22},
new double[]{0,15,6,0,25,0},
new double[]{0,0,18,25,0,14},
new double[]{0,0,22,0,14,0}
};
// 3、Kruskal原始边集合
List<LogisticsEdge> edgeList = new List<LogisticsEdge>()
{
new LogisticsEdge(0,1,12),
new LogisticsEdge(0,2,28),
new LogisticsEdge(1,2,8),
new LogisticsEdge(1,3,15),
new LogisticsEdge(2,3,6),
new LogisticsEdge(2,4,18),
new LogisticsEdge(2,5,22),
new LogisticsEdge(3,4,25),
new LogisticsEdge(4,5,14)
};
LogisticsRouteAppService appService = new LogisticsRouteAppService();
// Prim计算输出
Console.WriteLine("========== Prim算法-稠密网点物流规划 ==========");
LogisticsMST primMst = appService.BuildByPrim(adjMatrix, nodeList);
foreach (var item in primMst.GetDetailList())
{
Console.WriteLine($"{item.Item1} <--> {item.Item2} 运输成本:{item.Item3:0}千元");
}
Console.WriteLine($"全网最低总成本:{primMst.TotalCost:0} 千元\n");
// Kruskal计算输出
Console.WriteLine("========== Kruskal算法-稀疏跨城网点规划 ==========");
LogisticsMST krusMst = appService.BuildByKruskal(edgeList, nodeList);
foreach (var item in krusMst.GetDetailList())
{
Console.WriteLine($"{item.Item1} <--> {item.Item2} 运输成本:{item.Item3:0}千元");
}
Console.WriteLine($"全网最低总成本:{krusMst.TotalCost:0} 千元");
Console.ReadKey();
}
}
}
输出:

哲学管理(学)人生, 文学艺术生活, 自动(计算机学)物理(学)工作, 生物(学)化学逆境, 历史(学)测绘(学)时间, 经济(学)数学金钱(理财), 心理(学)医学情绪, 诗词美容情感, 美学建筑(学)家园, 解构建构(分析)整合学习, 智商情商(IQ、EQ)运筹(学)生存.---Geovin Du(涂聚文)
浙公网安备 33010602011771号