SwiftGraph

Swift Versions CocoaPods Version Carthage Compatible SPM Compatible CocoaPods Platforms Linux Compatible Twitter Contact Build Status Maintainability Test Coverage

SwiftGraph 是一个纯 Swift (无 Cocoa) 实现的图数据结构,适用于 Swift 支持的所有平台(iOS、macOS、Linux 等)。它支持带权图、无权图、有向图和无向图。它使用泛型来抽象顶点类型和权重类型。

它包含了大量的源代码文档、单元测试以及用于执行诸如广度优先搜索、深度优先搜索和 Dijkstra 算法等操作的搜索函数。此外,它还包括用于拓扑排序、Jarnik 算法(用于查找最小生成树)、检测 DAG(有向无环图)、枚举所有环等的实用函数。

安装

SwiftGraph 3.0 及以上版本需要 Swift 5 (Xcode 10.2)。使用 SwiftGraph 2.0 支持 Swift 4.2 (Xcode 10.1),SwiftGraph 1.5.1 支持 Swift 4.1 (Xcode 9),SwiftGraph 1.4.1 支持 Swift 3 (Xcode 8),SwiftGraph 1.0.6 支持 Swift 2 (Xcode 7),SwiftGraph 1.0.0 支持 Swift 1.2 (Xcode 6.3)。 SwiftGraph 支持 GNU/Linux 并在其上进行了测试。

CocoaPods

使用 CocoaPod SwiftGraph

Carthage

将以下内容添加到您的 Cartfile

github "davecom/SwiftGraph" ~> 3.1

Swift Package Manager (SPM)

使用此存储库作为您的依赖项。

手动

Sources 文件夹中的所有源文件复制到您的项目中。

技巧和窍门

示例

有关更多详细信息,请查看文档部分,但此示例构建了一个美国城市加权图并对其进行了一些操作,应该可以帮助您入门。

let cityGraph: WeightedGraph<String, Int> = WeightedGraph<String, Int>(vertices: ["Seattle", "San Francisco", "Los Angeles", "Denver", "Kansas City", "Chicago", "Boston", "New York", "Atlanta", "Miami", "Dallas", "Houston"])

cityGraph 是一个具有 String 顶点和 Int 边的权重的 WeightedGraph

cityGraph.addEdge(from: "Seattle", to:"Chicago", weight:2097)
cityGraph.addEdge(from: "Seattle", to:"Chicago", weight:2097)
cityGraph.addEdge(from: "Seattle", to: "Denver", weight:1331)
cityGraph.addEdge(from: "Seattle", to: "San Francisco", weight:807)
cityGraph.addEdge(from: "San Francisco", to: "Denver", weight:1267)
cityGraph.addEdge(from: "San Francisco", to: "Los Angeles", weight:381)
cityGraph.addEdge(from: "Los Angeles", to: "Denver", weight:1015)
cityGraph.addEdge(from: "Los Angeles", to: "Kansas City", weight:1663)
cityGraph.addEdge(from: "Los Angeles", to: "Dallas", weight:1435)
cityGraph.addEdge(from: "Denver", to: "Chicago", weight:1003)
cityGraph.addEdge(from: "Denver", to: "Kansas City", weight:599)
cityGraph.addEdge(from: "Kansas City", to: "Chicago", weight:533)
cityGraph.addEdge(from: "Kansas City", to: "New York", weight:1260)
cityGraph.addEdge(from: "Kansas City", to: "Atlanta", weight:864)
cityGraph.addEdge(from: "Kansas City", to: "Dallas", weight:496)
cityGraph.addEdge(from: "Chicago", to: "Boston", weight:983)
cityGraph.addEdge(from: "Chicago", to: "New York", weight:787)
cityGraph.addEdge(from: "Boston", to: "New York", weight:214)
cityGraph.addEdge(from: "Atlanta", to: "New York", weight:888)
cityGraph.addEdge(from: "Atlanta", to: "Dallas", weight:781)
cityGraph.addEdge(from: "Atlanta", to: "Houston", weight:810)
cityGraph.addEdge(from: "Atlanta", to: "Miami", weight:661)
cityGraph.addEdge(from: "Houston", to: "Miami", weight:1187)
cityGraph.addEdge(from: "Houston", to: "Dallas", weight:239)

便捷方法用于在各个顶点之间添加 WeightedEdge 连接。

let (distances, pathDict) = cityGraph.dijkstra(root: "New York", startDistance: 0)
var nameDistance: [String: Int?] = distanceArrayToVertexDict(distances: distances, graph: cityGraph)
// shortest distance from New York to San Francisco
let temp = nameDistance["San Francisco"] 
// path between New York and San Francisco
let path: [WeightedEdge<Int>] = pathDictToPath(from: cityGraph.indexOfVertex("New York")!, to: cityGraph.indexOfVertex("San Francisco")!, pathDict: pathDict)
let stops: [String] = cityGraph.edgesToVertices(edges: path)

使用 Dijkstra 算法找到图中各个顶点之间的最短路径。

let mst = cityGraph.mst()

找到连接图中所有顶点的最小生成树。

let cycles = cityGraph.detectCycles()

找到 cityGraph 中的所有环。

let isADAG = cityGraph.isDAG

由于 cityGraph 未被发现是有向无环图,因此 isADAGfalse

let result = cityGraph.findAll(from: "New York") { v in
    return v.characters.first == "S"
}

从纽约开始,对 cityGraph 中所有以字母“S”开头的城市执行广度优先搜索。

SwiftGraph 包含许多更有用的功能,但希望这个例子是一个不错的快速入门。

文档

源代码中使用了最新的 Apple 文档技术,包含了大量的文档 - 因此您应该能够直接按住 Alt 键并单击方法名称,以在 Xcode 中获取有关它的许多有用信息。我们还使用 Jazzy 生成 HTML 文档。此外,这里概述了 SwiftGraph 的每个组件

边将图中的顶点相互连接。

图是 SwiftGraph 的核心数据结构。所有顶点在插入到图中时都会被分配一个整数索引,并且通常通过索引引用它们比通过顶点的实际对象引用它们更快。

图实现了标准的 Swift 协议 Collection(用于迭代所有顶点以及通过下标按索引获取顶点)和 Codable。例如,以下示例在单独的行上打印图中的所有顶点

for v in g {  // g is a Graph<String>
    print(v)
}

我们可以使用下标通过索引获取特定的顶点

print(g[23]) // g is a Graph<String>

注意:目前,图是线程安全的。但是,一旦构建了图,如果您只进行查找和搜索(不删除顶点/边,也不添加顶点/边),那么您应该能够从多个线程执行此操作。完全线程安全的图形实现是可能的未来方向。

搜索

搜索方法在 Search.swift 中的 GraphWeightedGraph 的扩展中定义。

排序 & 其他

Sort.swiftGraph 的扩展提供了拓扑排序和检测 DAG 的工具。

MST.swiftWeightedGraph 的扩展可以从带权图中找到最小生成树。

Cycles.swiftGraph 的扩展会找到图中的所有循环。

Reversed.swiftGraph 的扩展会反转图中的所有边。

作者、许可和贡献者

SwiftGraph 由 David Kopec 和其他贡献者编写(请参阅 CONTRIBUTORS.md)。它是在 Apache 许可证下发布的(请参阅 LICENSE)。您可以在我的 GitHub 个人资料页面上找到我的电子邮件地址。我鼓励您在 GitHub 上提交 pull request 并提出 issue。

我衷心感谢多年来帮助改进 SwiftGraph 并不断激励我的所有贡献者。 按照 Apache 许可协议的规定,向 SwiftGraph 贡献代码意味着您也要以与原始项目相同的许可协议发布您的贡献。 然而,Apache 许可协议是宽松的,您可以自由地将 SwiftGraph 包含在商业、闭源产品中,只要您注明它及其作者(事实上,SwiftGraph 已经应用于多个产品中)。 有关详细信息,请参见 LICENSE 文件。

如果您在您的产品中使用 SwiftGraph,请与我联系并告知我。 这仅仅是让人觉得很酷的事情。

未来发展方向

该项目未来的发展方向可能包括: