Skip to content

核心概念速查

本文档提供 mbtgraph 核心概念的快速参考,帮助你快速上手。

图的顶点,代表实体。

// 创建节点 ID
let node_id = @core.NodeId(0)
// 节点数据可以是任意类型
let node_data = "User_Alice"

连接两个节点的线段,可带权重。

// 有向边:从 source 到 target
let edge = @core.Edge {
source: @core.NodeId(0),
target: @core.NodeId(1),
weight: Some(1.5),
}
// 无权边(权重为 None)
let unweighted_edge = @core.Edge { ... weight: None }

边的数值属性,表示距离、成本等。

// 带权重
let weighted = Some(10.0)
// 不带权重
let unweighted = None

所有存储必须实现的接口,提供 12 个只读方法:

pub trait GraphReadable {
node_count(self) -> Int // 节点数
edge_count(self) -> Int // 边数
contains_node(self, NodeId) -> Bool // 节点是否存在
contains_edge(self, NodeId, NodeId) -> Bool // 边是否存在
neighbors(self, NodeId) -> Iter[NodeId] // 邻居列表
degree(self, NodeId) -> Int // 度数
node_ids(self) -> Iter[NodeId] // 所有节点 ID
edges(self) -> Iter[(NodeId, NodeId, Double)] // 所有边 (from, to, weight)
get_node(self, NodeId) -> Double? // 获取节点数据
get_edge(self, NodeId, NodeId) -> Double? // 获取边数据
}

扩展自 GraphReadable,增加 5 个写入方法:

pub trait GraphWritable : GraphReadable {
add_node(Self, Double) -> NodeId // 添加节点,返回 NodeId
remove_node(Self, NodeId) -> Bool // 删除节点
add_edge(Self, NodeId, NodeId, Double) -> Result[Unit, GraphError] // 添加边
remove_edge(Self, NodeId, NodeId) -> Bool // 删除边
clear(Self) -> Unit // 清空图
}
Trait继承自新增方法适用场景
GraphDirectedReadable+6 (入边查询)有向图
GraphFullGraphWritable + GraphDirected-便捷别名
GraphBatchReadableReadable+2 (批量操作)CSR/CSC
存储空间复杂度特点适用场景
DirectedAdjListO(V+E)⭐ 通用推荐大多数场景
DirectedMatrixO(V²)稠密图优化小规模稠密图
EdgeListO(E)边集合MST/Kruskal
CSRO(V+E)缓存友好大规模静态图
CSCO(V+E)入度 O(1)入边密集查询
存储空间复杂度特点适用场景
UndirectedAdjListO(V+E/2)半存储节省 50%无向通用图
UndirectedMatrixO(V²/2)对称矩阵小型无向图
UndirectedEdgeListO(E/2)无向边集无向 MST
// 广度优先搜索
pub fn[G : @core.GraphReadable] bfs(graph : G, start : NodeId) -> BfsResult
// 深度优先搜索
pub fn[G : @core.GraphReadable] dfs(graph : G, start : NodeId) -> DfsResult
// Dijkstra(非负权)
pub fn[G : @core.GraphReadable] dijkstra(graph : G, source : NodeId) -> ShortestPathResult
// Bellman-Ford(允许负权)
pub fn bellman_ford(graph : FlowNetwork, source : Int) -> BellmanFordResult
// Kruskal(需要 EdgeIterable)
pub fn kruskal(graph : G) -> MstResult
// Prim
pub fn prim(graph : G, start : NodeId) -> MstResult

mbtgraph 使用 Result[T, E] 类型处理错误:

match @core.GraphWritable::add_edge(g, invalid_source, target, 1.0) {
Ok(_) => {
// 成功
}
Err(e) => {
// 错误:处理错误情况
match e {
@core.GraphError::NodeNotFound(id) => println("节点 \{id} 不存在")
@core.GraphError::DuplicateEdge => println("边已存在")
_ => println("未知错误")
}
}
}
需要什么功能?
├─ 只读访问?
│ └─ 任何实现了 GraphReadable 的存储
├─ 动态增删?
│ └─ 需要 GraphWritable(AdjList / Matrix / EdgeList)
├─ 有向图?
│ └─ 需要 GraphDirected(有向变体)
├─ 大规模静态图 (>100K 节点)?
│ └─ 推荐 CSR 或 CSC
├─ MST / Kruskal 算法?
│ └─ 需要 EdgeIterable(EdgeList)
└─ 不知道选哪个?
└─ 默认 DirectedAdjList ⭐