SwiftPriorityQueue 是一个纯 Swift (无 Cocoa) 实现的通用优先级队列数据结构,适用于所有支持 Swift 的平台(macOS、iOS、Linux 等)。它具有直观的接口,可以与任何实现了 Comparable
协议的类型一起使用。它使用元素之间的比较,而不是单独的数字优先级来确定顺序。
在内部,SwiftPriorityQueue 使用经典的二叉堆,从而实现 O(lg n) 的入队和出队操作。它包含源代码文档、一个基于 A* 算法的示例迷宫求解程序(适用于 macOS)和单元测试(特别欢迎提交更多单元测试的 pull request)。
Sequence
和 IteratorProtocol
)1.3.0 及以上版本支持 Swift 5。Swift 4 请使用 1.2.1 版本。Swift 3 和 Swift 2 请使用 1.1.2 版本。Swift 1.2 请使用 1.0 版本。
使用 CocoaPod SwiftPriorityQueue
。
将此仓库添加为依赖项。
将 SwiftPriorityQueue.swift
复制到您的项目中。
源代码中有大量使用标准 Swift 文档技术(与 Jazzy 兼容)的文档。 但本质上,SwiftPriorityQueue 具有您期望的三个关键方法 - push()
、pop()
和 peek()
。
创建新的 PriorityQueue
时,您可以选择指定优先级队列是升序还是降序。 这意味着什么? 如果优先级队列是升序的,则其最小值(由其 Comparable
实现,即 <
确定)将首先被弹出,如果是降序的,则其最大值将首先被弹出。
var pq: PriorityQueue<String> = PriorityQueue<String>(ascending: true)
您还可以提供一个起始值数组,以便将其按顺序立即推入优先级队列。
var pq: PriorityQueue<Int> = PriorityQueue<Int>(startingValues: [6, 2, 3, 235, 4, 500])
或者您可以同时指定两者。
var pq: PriorityQueue<Int> = PriorityQueue<Int>(ascending: false, startingValues: [6, 2, 3, 235, 4, 500])
或者您可以两者都不指定。 默认情况下,PriorityQueue
是降序且为空的。 您可能已经注意到,PriorityQueue 采用泛型类型。 此类型必须是 Comparable
,因为它的比较将用于确定优先级。 这意味着您的自定义类型必须实现 Comparable
并利用重写的 <
来确定优先级。
PriorityQueue
具有您期望优先级队列数据结构具有的所有标准方法。
push(element: T)
- 将一个元素放入优先级队列。 O(lg n)push(element: T, maxCount: Int) -> T?
- 添加一个元素,同时将优先级队列的大小限制为 maxCount
。 如果在添加后优先级队列中的元素多于 maxCount
,则优先级最低的元素将被丢弃并返回。 请注意,这是低效的,因为这是一个二叉堆,因此只有优先级最高的项目才能有效检索。 O(n)pop() -> T?
- 返回并删除具有最高(如果升序则为最低)优先级的元素,如果优先级队列为空,则返回 nil
。 O(lg n)peek() -> T?
- 返回具有最高(如果升序则为最低)优先级的元素,如果优先级队列为空,则返回 nil
。 O(1)clear()
- 从优先级队列中删除所有元素。remove(item: T)
- 删除优先级队列中首次找到的 item 实例。 如果未找到,则静默返回。 O(n)removeAll(item: T)
- 通过重复调用 remove()
来删除优先级队列中 item 的所有实例。 如果未找到,则静默返回。count: Int
- 优先级队列中的元素数。isEmpty: Bool
- 如果优先级队列中没有元素,则为 true
,否则为 false
。PriorityQueue
实现了 IteratorProtocol
、Sequence
和 Collection
,因此您可以将 PriorityQueue
视为任何其他 Swift 序列/集合。 这意味着您可以在 PriorityQueue
上使用 Swift 标准库函数,并像这样迭代 PriorityQueue
for item in pq { // pq is a PriorityQueue<String>
print(item)
}
这样做时,PriorityQueue
中的每个项目都会按顺序弹出。 PriorityQueue
还实现了 CustomStringConvertible
和 CustomDebugStringConvertible
。
print(pq)
注意:PriorityQueue
是非线程安全的(不要同时从多个线程操作它)。
假设您只想在优先级队列中保留 maxCount
个优先级最高的项目。
例如,假设您只希望优先级队列永远只有 4 个元素
var pq: PriorityQueue<Int> = PriorityQueue<Int>()
let maxCount = 4
pq.push(4, maxCount: maxCount)
pq.push(5, maxCount: maxCount)
pq.push(0, maxCount: maxCount)
pq.push(3, maxCount: maxCount)
pq.push(6, maxCount: maxCount)
pq.push(1, maxCount: maxCount)
在这种情况下,在推送了 4 个元素后,只保留了最小的元素(因为顺序是 ascending
)。 因此,最终的优先级队列包含元素 0、1、3、4。
A* 是一种使用优先级队列的寻路算法。 SwiftPriorityQueue 附带的示例程序是一个使用 A* 的迷宫求解器。 如果您想在 astar.swift
中重用此算法,可以找到一些源代码文档。
SwiftPriorityQueue 由 David Kopec (@davecom on GitHub) 编写,并根据 MIT 许可证发布(请参阅 LICENSE
)。 您可以在我的 GitHub 个人资料页面上找到我的联系方式。 我鼓励您提交 pull request 并在 GitHub 上提出 issue。 感谢多年来的所有贡献者。