
項(xiàng)目結(jié)構(gòu)/* # 版權(quán)所有 2026 ?涂聚文有限公司? ? # 許可信息查看言語(yǔ)成了邀功盡責(zé)的功臣還需要行爲(wèi)每日來(lái)值班嗎 # 描述 Prim Algorithms and Kruskal Algorithms 普里姆算法和克魯斯卡爾算法 # Author : geovindu,Geovin Du 涂聚文. # IDE : goLang 2024.3.6 go 26.2 # os : windows 10 # database : mysql 9.0 sql server 2019, postgreSQL 17.0 Oracle 21c Neo4j # Datetime : 2026/8/7 23:04 # User : geovindu # Product : GoLand # Project : goalgorithms # File : aggregate_root.go */ package common // AggregateRoot 聚合根頂層抽象 type AggregateRoot struct { domainEvents []interface{} } // GetDomainEvents 獲取領(lǐng)域事件 func (ar *AggregateRoot) GetDomainEvents() []interface{} { copyEvents : make([]interface{}, len(ar.domainEvents)) copy(copyEvents, ar.domainEvents) return copyEvents } // ClearDomainEvents 清空領(lǐng)域事件 func (ar *AggregateRoot) ClearDomainEvents() { ar.domainEvents ar.domainEvents[:0] } /* # 版權(quán)所有 2026 ?涂聚文有限公司? ? # 許可信息查看言語(yǔ)成了邀功盡責(zé)的功臣還需要行爲(wèi)每日來(lái)值班嗎 # 描述 Prim Algorithms and Kruskal Algorithms 普里姆算法和克魯斯卡爾算法 # Author : geovindu,Geovin Du 涂聚文. # IDE : goLang 2024.3.6 go 26.2 # os : windows 10 # database : mysql 9.0 sql server 2019, postgreSQL 17.0 Oracle 21c Neo4j # Datetime : 2026/8/7 23:05 # User : geovindu # Product : GoLand # Project : goalgorithms # File : entity.go */ package common // Entity 實(shí)體頂層抽象擁有唯一ID type Entity struct { id int } // NewEntity 創(chuàng)建實(shí)體 func NewEntity(id int) Entity { return Entity{id: id} } // ID 獲取實(shí)體唯一標(biāo)識(shí) func (e Entity) ID() int { return e.id } /* # 版權(quán)所有 2026 ?涂聚文有限公司? ? # 許可信息查看言語(yǔ)成了邀功盡責(zé)的功臣還需要行爲(wèi)每日來(lái)值班嗎 # 描述 Prim Algorithms and Kruskal Algorithms 普里姆算法和克魯斯卡爾算法 # Author : geovindu,Geovin Du 涂聚文. # IDE : goLang 2024.3.6 go 26.2 # os : windows 10 # database : mysql 9.0 sql server 2019, postgreSQL 17.0 Oracle 21c Neo4j # Datetime : 2026/8/7 23:05 # User : geovindu # Product : GoLand # Project : goalgorithms # File : value_object.go */ package common // ValueObject 值對(duì)象頂層抽象不可變基于屬性相等判斷 type ValueObject interface { Equal(other ValueObject) bool } /* # 版權(quán)所有 2026 ?涂聚文有限公司? ? # 許可信息查看言語(yǔ)成了邀功盡責(zé)的功臣還需要行爲(wèi)每日來(lái)值班嗎 # 描述 Prim Algorithms and Kruskal Algorithms 普里姆算法和克魯斯卡爾算法 # Author : geovindu,Geovin Du 涂聚文. # IDE : goLang 2024.3.6 go 26.2 # os : windows 10 # database : mysql 9.0 sql server 2019, postgreSQL 17.0 Oracle 21c Neo4j # Datetime : 2026/8/7 23:06 # User : geovindu # Product : GoLand # Project : goalgorithms # File : domain_err.go */ package common import fmt // DomainErr 統(tǒng)一領(lǐng)域業(yè)務(wù)異常 type DomainErr struct { Msg string } func (e *DomainErr) Error() string { return fmt.Sprintf([領(lǐng)域異常] %s, e.Msg) } // NewDomainErr 構(gòu)造領(lǐng)域異常 func NewDomainErr(msg string) error { return DomainErr{Msg: msg} } /* # 版權(quán)所有 2026 ?涂聚文有限公司? ? # 許可信息查看言語(yǔ)成了邀功盡責(zé)的功臣還需要行爲(wèi)每日來(lái)值班嗎 # 描述 Prim Algorithms and Kruskal Algorithms 普里姆算法和克魯斯卡爾算法 # Author : geovindu,Geovin Du 涂聚文. # IDE : goLang 2024.3.6 go 26.2 # os : windows 10 # database : mysql 9.0 sql server 2019, postgreSQL 17.0 Oracle 21c Neo4j # Datetime : 2026/8/7 23:06 # User : geovindu # Product : GoLand # Project : goalgorithms # File : union_find.go */ package common // UnionFind 并查集路徑壓縮Kruskal算法依賴(lài) type UnionFind struct { parent []int } // NewUnionFind 初始化并查集 func NewUnionFind(size int) *UnionFind { parent : make([]int, size) for i : 0; i size; i { parent[i] i } return UnionFind{parent: parent} } // Find 查找根節(jié)點(diǎn)路徑壓縮 func (uf *UnionFind) Find(x int) int { if uf.parent[x] ! x { uf.parent[x] uf.Find(uf.parent[x]) } return uf.parent[x] } // Union 合并兩個(gè)集合true合并成功無(wú)環(huán)false成環(huán) func (uf *UnionFind) Union(x, y int) bool { rootX : uf.Find(x) rootY : uf.Find(y) if rootX rootY { return false } uf.parent[rootY] rootX return true } /* # 版權(quán)所有 2026 ?涂聚文有限公司? ? # 許可信息查看言語(yǔ)成了邀功盡責(zé)的功臣還需要行爲(wèi)每日來(lái)值班嗎 # 描述 Prim Algorithms and Kruskal Algorithms 普里姆算法和克魯斯卡爾算法 # Author : geovindu,Geovin Du 涂聚文. # IDE : goLang 2024.3.6 go 26.2 # os : windows 10 # database : mysql 9.0 sql server 2019, postgreSQL 17.0 Oracle 21c Neo4j # Datetime : 2026/8/7 23:07 # User : geovindu # Product : GoLand # Project : goalgorithms # File : logistics_node.go */ package model import goalgorithms/primkruskal/common // LogisticsNode 物流網(wǎng)點(diǎn)【實(shí)體】 // 代表珠寶供應(yīng)鏈節(jié)點(diǎn)礦區(qū)、加工廠、倉(cāng)儲(chǔ)、線(xiàn)下門(mén)店 type LogisticsNode struct { common.Entity nodeName string // 網(wǎng)點(diǎn)名稱(chēng) nodeCategory string // 網(wǎng)點(diǎn)類(lèi)型原料礦區(qū)/加工中心/倉(cāng)儲(chǔ)中心/線(xiàn)下門(mén)店 } // NewLogisticsNode 構(gòu)造網(wǎng)點(diǎn)實(shí)體 func NewLogisticsNode(id int, name, category string) LogisticsNode { return LogisticsNode{ Entity: common.NewEntity(id), nodeName: name, nodeCategory: category, } } // NodeName 獲取網(wǎng)點(diǎn)名稱(chēng) func (n LogisticsNode) NodeName() string { return n.nodeName } // NodeCategory 獲取網(wǎng)點(diǎn)類(lèi)型 func (n LogisticsNode) NodeCategory() string { return n.nodeCategory } /* # 版權(quán)所有 2026 ?涂聚文有限公司? ? # 許可信息查看言語(yǔ)成了邀功盡責(zé)的功臣還需要行爲(wèi)每日來(lái)值班嗎 # 描述 Prim Algorithms and Kruskal Algorithms 普里姆算法和克魯斯卡爾算法 # Author : geovindu,Geovin Du 涂聚文. # IDE : goLang 2024.3.6 go 26.2 # os : windows 10 # database : mysql 9.0 sql server 2019, postgreSQL 17.0 Oracle 21c Neo4j # Datetime : 2026/8/7 23:07 # User : geovindu # Product : GoLand # Project : goalgorithms # File : logistics_edge.go */ package model import goalgorithms/primkruskal/common // LogisticsEdge 物流線(xiàn)路【值對(duì)象】 // 兩點(diǎn)間運(yùn)輸鏈路cost為綜合成本路費(fèi)押運(yùn)保險(xiǎn)貨品損耗單位千元 type LogisticsEdge struct { startID int endID int cost float64 } // NewLogisticsEdge 構(gòu)造線(xiàn)路值對(duì)象 func NewLogisticsEdge(start, end int, cost float64) LogisticsEdge { return LogisticsEdge{ startID: start, endID: end, cost: cost, } } func (e LogisticsEdge) Equal(other common.ValueObject) bool { oe, ok : other.(LogisticsEdge) if !ok { return false } return e.startID oe.startID e.endID oe.endID e.cost oe.cost } func (e LogisticsEdge) StartID() int { return e.startID } func (e LogisticsEdge) EndID() int { return e.endID } func (e LogisticsEdge) Cost() float64 { return e.cost } /* # 版權(quán)所有 2026 ?涂聚文有限公司? ? # 許可信息查看言語(yǔ)成了邀功盡責(zé)的功臣還需要行爲(wèi)每日來(lái)值班嗎 # 描述 Prim Algorithms and Kruskal Algorithms 普里姆算法和克魯斯卡爾算法 # Author : geovindu,Geovin Du 涂聚文. # IDE : goLang 2024.3.6 go 26.2 # os : windows 10 # database : mysql 9.0 sql server 2019, postgreSQL 17.0 Oracle 21c Neo4j # Datetime : 2026/8/7 23:08 # User : geovindu # Product : GoLand # Project : goalgorithms # File : logistics_mst.go */ package model import goalgorithms/primkruskal/common // LogisticsMST 最小生成樹(shù)【聚合根】 // 聚合全部網(wǎng)點(diǎn)、MST選中線(xiàn)路、總運(yùn)輸成本 type LogisticsMST struct { common.AggregateRoot AllNodes []LogisticsNode MstEdges []LogisticsEdge TotalCost float64 } // SetNodes 綁定全部網(wǎng)點(diǎn) func (m *LogisticsMST) SetNodes(nodes []LogisticsNode) { m.AllNodes nodes } // SetMstResult 寫(xiě)入MST計(jì)算結(jié)果 func (m *LogisticsMST) SetMstResult(edges []LogisticsEdge, totalCost float64) { m.MstEdges edges m.TotalCost totalCost } // GetEdgeDetail 格式化線(xiàn)路詳情[(起點(diǎn)名,終點(diǎn)名,成本)] func (m *LogisticsMST) GetEdgeDetail() [][3]interface{} { nodeMap : make(map[int]string, len(m.AllNodes)) for _, node : range m.AllNodes { nodeMap[node.ID()] node.NodeName() } var res [][3]interface{} for _, edge : range m.MstEdges { sName : nodeMap[edge.StartID()] eName : nodeMap[edge.EndID()] res append(res, [3]interface{}{sName, eName, edge.Cost()}) } return res } /* # 版權(quán)所有 2026 ?涂聚文有限公司? ? # 許可信息查看言語(yǔ)成了邀功盡責(zé)的功臣還需要行爲(wèi)每日來(lái)值班嗎 # 描述 Prim Algorithms and Kruskal Algorithms 普里姆算法和克魯斯卡爾算法 # Author : geovindu,Geovin Du 涂聚文. # IDE : goLang 2024.3.6 go 26.2 # os : windows 10 # database : mysql 9.0 sql server 2019, postgreSQL 17.0 Oracle 21c Neo4j # Datetime : 2026/8/7 23:08 # User : geovindu # Product : GoLand # Project : goalgorithms # File : prim.go */ package algorithm import ( goalgorithms/primkruskal/common goalgorithms/primkruskal/domain/model math ) // PrimAlgorithm Prim最小生成樹(shù)【領(lǐng)域算法服務(wù)】 // 適用稠密圖、門(mén)店/加工廠密集場(chǎng)景 type PrimAlgorithm struct{} // Calculate 執(zhí)行Prim計(jì)算返回MST線(xiàn)路、總成本、領(lǐng)域異常 func (p PrimAlgorithm) Calculate(adjMatrix [][]float64, nodes []model.LogisticsNode) ([]model.LogisticsEdge, float64, error) { nodeCnt : len(nodes) if nodeCnt 0 { return nil, 0, common.NewDomainErr(網(wǎng)點(diǎn)集合不能為空無(wú)法生成物流路網(wǎng)) } const INF math.MaxFloat64 inMST : make([]bool, nodeCnt) minDist : make([]float64, nodeCnt) preNode : make([]int, nodeCnt) for i : range minDist { minDist[i] INF preNode[i] -1 } minDist[0] 0 totalCost : 0.0 var mstEdges []model.LogisticsEdge for round : 0; round nodeCnt; round { // 選取距離MST最近未加入節(jié)點(diǎn) selectIdx : -1 minVal : INF for i : 0; i nodeCnt; i { if !inMST[i] minDist[i] minVal { minVal minDist[i] minVal minDist[i] selectIdx i } } if selectIdx -1 { return nil, 0, common.NewDomainErr(網(wǎng)點(diǎn)圖不連通無(wú)法構(gòu)建完整物流最小生成樹(shù)) } inMST[selectIdx] true totalCost minVal // 記錄邊 preIdx : preNode[selectIdx] if preIdx ! -1 { edge : model.NewLogisticsEdge(preIdx, selectIdx, adjMatrix[preIdx][selectIdx]) mstEdges append(mstEdges, edge) } // 松弛更新鄰接點(diǎn)距離 for j : 0; j nodeCnt; j { w : adjMatrix[selectIdx][j] if !inMST[j] w 0 w minDist[j] { minDist[j] w preNode[j] selectIdx } } } return mstEdges, totalCost, nil } /* # 版權(quán)所有 2026 ?涂聚文有限公司? ? # 許可信息查看言語(yǔ)成了邀功盡責(zé)的功臣還需要行爲(wèi)每日來(lái)值班嗎 # 描述 Prim Algorithms and Kruskal Algorithms 普里姆算法和克魯斯卡爾算法 # Author : geovindu,Geovin Du 涂聚文. # IDE : goLang 2024.3.6 go 26.2 # os : windows 10 # database : mysql 9.0 sql server 2019, postgreSQL 17.0 Oracle 21c Neo4j # Datetime : 2026/8/7 23:09 # User : geovindu # Product : GoLand # Project : goalgorithms # File : kruskal.go */ package algorithm import ( goalgorithms/primkruskal/common goalgorithms/primkruskal/domain/model sort ) // KruskalAlgorithm Kruskal最小生成樹(shù)【領(lǐng)域算法服務(wù)】 // 適用稀疏圖、跨城分散門(mén)店、礦區(qū)組網(wǎng) type KruskalAlgorithm struct{} // Calculate 執(zhí)行Kruskal計(jì)算 func (k KruskalAlgorithm) Calculate(edges []model.LogisticsEdge, nodes []model.LogisticsNode) ([]model.LogisticsEdge, float64, error) { nodeCnt : len(nodes) if nodeCnt 0 { return nil, 0, common.NewDomainErr(網(wǎng)點(diǎn)集合不能為空無(wú)法生成物流路網(wǎng)) } // 邊升序排序 sort.Slice(edges, func(i, j int) bool { return edges[i].Cost() edges[j].Cost() }) uf : common.NewUnionFind(nodeCnt) var mstEdges []model.LogisticsEdge totalCost : 0.0 for _, e : range edges { if uf.Union(e.StartID(), e.EndID()) { mstEdges append(mstEdges, e) totalCost e.Cost() if len(mstEdges) nodeCnt-1 { break } } } if len(mstEdges) ! nodeCnt-1 { return nil, 0, common.NewDomainErr(網(wǎng)點(diǎn)圖不連通無(wú)法構(gòu)建完整物流最小生成樹(shù)) } return mstEdges, totalCost, nil } /* # 版權(quán)所有 2026 ?涂聚文有限公司? ? # 許可信息查看言語(yǔ)成了邀功盡責(zé)的功臣還需要行爲(wèi)每日來(lái)值班嗎 # 描述 Prim Algorithms and Kruskal Algorithms 普里姆算法和克魯斯卡爾算法 # Author : geovindu,Geovin Du 涂聚文. # IDE : goLang 2024.3.6 go 26.2 # os : windows 10 # database : mysql 9.0 sql server 2019, postgreSQL 17.0 Oracle 21c Neo4j # Datetime : 2026/8/7 23:09 # User : geovindu # Product : GoLand # Project : goalgorithms # File : logistics_route_service.go */ package application import ( goalgorithms/primkruskal/domain/algorithm goalgorithms/primkruskal/domain/model ) // LogisticsRouteApplicationService 物流路線(xiàn)應(yīng)用服務(wù) // 職責(zé)編排調(diào)用領(lǐng)域算法、組裝聚合根對(duì)外提供統(tǒng)一業(yè)務(wù)接口 type LogisticsRouteApplicationService struct{} // BuildMSTByPrim Prim生成最小生成樹(shù) func (l LogisticsRouteApplicationService) BuildMSTByPrim(matrix [][]float64, nodes []model.LogisticsNode) (*model.LogisticsMST, error) { prim : algorithm.PrimAlgorithm{} edges, cost, err : prim.Calculate(matrix, nodes) if err ! nil { return nil, err } mst : model.LogisticsMST{} mst.SetNodes(nodes) mst.SetMstResult(edges, cost) return mst, nil } // BuildMSTByKruskal Kruskal生成最小生成樹(shù) func (l LogisticsRouteApplicationService) BuildMSTByKruskal(edges []model.LogisticsEdge, nodes []model.LogisticsNode) (*model.LogisticsMST, error) { krus : algorithm.KruskalAlgorithm{} edges, cost, err : krus.Calculate(edges, nodes) if err ! nil { return nil, err } mst : model.LogisticsMST{} mst.SetNodes(nodes) mst.SetMstResult(edges, cost) return mst, nil }調(diào)用/* # 版權(quán)所有 2026 ?涂聚文有限公司? ? # 許可信息查看言語(yǔ)成了邀功盡責(zé)的功臣還需要行爲(wèi)每日來(lái)值班嗎 # 描述 Prim Algorithms and Kruskal Algorithms 普里姆算法和克魯斯卡爾算法 # Author : geovindu,Geovin Du 涂聚文. # IDE : goLang 2024.3.6 go 26.2 # os : windows 10 # database : mysql 9.0 sql server 2019, postgreSQL 17.0 Oracle 21c Neo4j # Datetime : 2026/8/7 23:10 # User : geovindu # Product : GoLand # Project : goalgorithms # File : primkruskalbll.go */ package bll import ( fmt goalgorithms/primkruskal/application goalgorithms/primkruskal/domain/model log ) func PrimkruskalMain() { // 1. 初始化珠寶供應(yīng)鏈網(wǎng)點(diǎn)實(shí)體 nodeList : []model.LogisticsNode{ model.NewLogisticsNode(0, 緬甸翡翠礦區(qū)A, 原料礦區(qū)), model.NewLogisticsNode(1, 云南分揀加工廠, 加工中心), model.NewLogisticsNode(2, 深圳總倉(cāng)儲(chǔ)中心, 倉(cāng)儲(chǔ)中心), model.NewLogisticsNode(3, 廣州旗艦門(mén)店, 線(xiàn)下門(mén)店), model.NewLogisticsNode(4, 上海門(mén)店, 線(xiàn)下門(mén)店), model.NewLogisticsNode(5, 北京門(mén)店, 線(xiàn)下門(mén)店), } // 2. Prim 鄰接矩陣 單位千元0無(wú)直達(dá)線(xiàn)路 adjMatrix : [][]float64{ {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 原始邊列表 rawEdges : []model.LogisticsEdge{ model.NewLogisticsEdge(0, 1, 12), model.NewLogisticsEdge(0, 2, 28), model.NewLogisticsEdge(1, 2, 8), model.NewLogisticsEdge(1, 3, 15), model.NewLogisticsEdge(2, 3, 6), model.NewLogisticsEdge(2, 4, 18), model.NewLogisticsEdge(2, 5, 22), model.NewLogisticsEdge(3, 4, 25), model.NewLogisticsEdge(4, 5, 14), } appService : application.LogisticsRouteApplicationService{} // Prim算法執(zhí)行 fmt.Println( Prim算法-稠密網(wǎng)點(diǎn)物流規(guī)劃 ) primMST, err : appService.BuildMSTByPrim(adjMatrix, nodeList) if err ! nil { log.Fatal(err) } primDetail : primMST.GetEdgeDetail() for _, item : range primDetail { fmt.Printf(%s -- %s 運(yùn)輸成本%.0f千元\n, item[0], item[1], item[2]) } fmt.Printf(全網(wǎng)最低總成本%.0f 千元\n\n, primMST.TotalCost) // Kruskal算法執(zhí)行 fmt.Println( Kruskal算法-稀疏跨城網(wǎng)點(diǎn)規(guī)劃 ) krusMST, err : appService.BuildMSTByKruskal(rawEdges, nodeList) if err ! nil { log.Fatal(err) } krusDetail : krusMST.GetEdgeDetail() for _, item : range krusDetail { fmt.Printf(%s -- %s 運(yùn)輸成本%.0f千元\n, item[0], item[1], item[2]) } fmt.Printf(全網(wǎng)最低總成本%.0f 千元\n, krusMST.TotalCost) }代碼實(shí)現(xiàn)了珠寶供應(yīng)鏈物流網(wǎng)絡(luò)的最小生成樹(shù)(MST)優(yōu)化方案包含Prim和Kruskal兩種算法。代碼采用領(lǐng)域驅(qū)動(dòng)設(shè)計(jì)(DDD)架構(gòu)包含實(shí)體、值對(duì)象、聚合根等核心概念。主要功能定義物流節(jié)點(diǎn)實(shí)體(LogisticsNode)和邊值對(duì)象(LogisticsEdge)實(shí)現(xiàn)Prim算法(稠密圖優(yōu)化)和Kruskal算法(稀疏圖優(yōu)化)提供應(yīng)用服務(wù)層統(tǒng)一接口計(jì)算并輸出MST路徑和最低總成本示例演示了6個(gè)節(jié)點(diǎn)(礦區(qū)、加工廠、倉(cāng)儲(chǔ)、門(mén)店)的物流網(wǎng)絡(luò)優(yōu)化分別用兩種算法計(jì)算最優(yōu)運(yùn)輸路線(xiàn)和成本。輸出顯示各節(jié)點(diǎn)間最優(yōu)連接方式及全網(wǎng)最低運(yùn)輸總成本。輸出