swift中的优先队列
Posted
技术标签:
【中文标题】swift中的优先队列【英文标题】:Priority Queue in swift 【发布时间】:2014-07-01 16:40:14 【问题描述】:我正在尝试实现 Dijkstra 算法的一个版本,以找到公共汽车从头到尾的最短路线。不幸的是,我似乎找不到 swift 提供一种优先级队列的库或其他方式,所以看来我必须自己编写代码。
话虽如此,任何人都可以为我指出正确的方向吗?
目前我的想法如下:
编写一个保存优先级数组的类。在这个类中将有一个方法接收一个值,将其添加到优先级数组中,然后根据优先级(在本例中为距离)对其进行排序。还有一个 get 函数,它从数组中返回最高优先级的项目。
我想知道我对优先级队列的理解是否接近或仍然遥遥无期。
谢谢。
编辑:
到目前为止,这是我的代码。似乎太短太粗暴了……我一定是在概念上遗漏了一些东西。
var priorityQueue = Dictionary<String, Int>()
var firstElement: String = ""
func push(name: String, distance: Int)
priorityQueue[name] = distance
var myArr = Array(priorityQueue.keys)
var sortedKeys = sort(myArr)
var obj1 = self.priorityQueue[$0] // get obj associated w/ key 1
var obj2 = self.priorityQueue[$1] // get obj associated w/ key 2
return obj1 > obj2
firstElement = myArr[0]
var tempPriorityQueue = Dictionary<String, Int>()
for val in myArr
tempPriorityQueue[val] = priorityQueue[val]
priorityQueue = tempPriorityQueue
func pop() -> String
priorityQueue.removeValueForKey(firstElement)
【问题讨论】:
大致正确。该方法将值和优先级键作为参数。它将根据优先级键找到内部数据结构中保存对的位置以放置它。现在考虑如何设置该数据结构。您需要一个易于在中间添加、易于从中删除且易于进入开头的数据结构。如果您能找到将配对放在哪里开始(它会自行排序),则不必对任何内容进行排序。 编写一些代码并发布它以获得更多有用的反馈。这里和在线也有大量资源,其中包含实施细节。 Dijkstra's algorithm with priority queue 的可能重复项 谢谢@Al.Sal,我会尽快发布一些代码。我对我现在需要做什么有了更好的了解。 @kuast,我看到了这个问题。我的不同,因为如果有人对在哪里看有一些建议,它会迅速具体化。该问题还包括诸如更新周围节点等我没有的问题。在尝试从 OP 的角度看待问题之前,不要这么快对问题做出负面判断。 【参考方案1】:您可能有兴趣查看我编写的两个开源项目。第一个是SwiftPriorityQueue:https://github.com/davecom/SwiftPriorityQueue
您对优先级队列的实现在 O(n lg n) 上进行排序。大多数优先级队列的实现,包括 SwiftPriorityQueue,都使用二进制堆作为后备存储。它们具有在 O(lg n) 中运行的推送操作和在 O(lg n) 中运行的弹出操作。因此,您的怀疑是正确的 - 您当前的实现不太可能非常高效(尽管 pop 在技术上更快)。
第二个是SwiftGraph:https://github.com/davecom/SwiftGraph
SwiftGraph 包含 Dijkstra 算法的实现。
令我惊讶的是,这两个项目都不太容易找到,因为它们已经推出一年多了,并且相当受欢迎,但根据去年对这个问题的当前答案,我似乎需要努力提高可发现性。
【讨论】:
【参考方案2】:您应该使用堆排序作为优先级。我认为这是最优的!在操场上试试吧!
import Foundation
typealias PriorityDefinition<P> = (_ p1: P, _ p2: P) -> (Bool)
class PriorityQueue<E, P: Hashable>
var priDef: PriorityDefinition<P>!
var elemments = [P: [E]]()
var priority = [P]()
init(_ priDef: @escaping PriorityDefinition<P>)
self.priDef = priDef
func enqueue(_ element: E!, _ priorityValue: P!)
if let _ = elemments[priorityValue]
elemments[priorityValue]!.append(element)
else
elemments[priorityValue] = [element]
if !priority.contains(priorityValue)
priority.append(priorityValue)
let lastIndex = priority.count - 1
siftUp(0, lastIndex, lastIndex)
func dequeue() -> E?
var result: E? = nil
if priority.count > 0
var p = priority.first!
if elemments[p]!.count == 1
if priority.count > 1
let _temp = priority[0]
priority[0] = priority[priority.count - 1]
priority[priority.count - 1] = _temp
p = priority.last!
siftDown(0, priority.count - 2)
result = elemments[p]!.removeFirst()
elemments[p] = nil
priority.remove(at: priority.index(of: p)!)
else
result = elemments[p]!.removeFirst()
return result
func siftDown(_ start: Int, _ end: Int)
let iLeftChild = 2 * start + 1
if iLeftChild <= end
var largestChild = priDef(priority[iLeftChild], priority[start]) ? iLeftChild : start
let iRightChild = 2 * start + 2
if iRightChild <= end
if priDef(priority[iRightChild], priority[iLeftChild])
largestChild = iRightChild
if largestChild == start
return
else
let _temp = priority[start]
priority[start] = priority[largestChild]
priority[largestChild] = _temp
siftDown(largestChild, end)
func siftUp(_ start: Int, _ end: Int, _ nodeIndex: Int)
let parent = (nodeIndex - 1) / 2
if parent >= start
if priDef(priority[nodeIndex], priority[parent])
let _temp = priority[nodeIndex]
priority[nodeIndex] = priority[parent]
priority[parent] = _temp
siftUp(start, end, parent)
else
return
func isEmpty() -> Bool
return priority.count == 0
let Q = PriorityQueue<Int, Int> (p1: Int, p2: Int) -> (Bool) in
return p1 > p2
let n = 999
for i in 0...n - 1
let start = NSDate().timeIntervalSince1970
Q.enqueue(i, i)
let end = NSDate().timeIntervalSince1970
print(end - start)
【讨论】:
【参考方案3】:查看“堆排序”的代码。 Heapsort 创建一个“堆”,它基本上是一个优先级队列,首先具有最大元素,然后它反复弹出 heap = 优先级队列的最大元素,将其移动到数组的末尾,并将先前的最后一个数组元素添加到优先队列。
在优先级队列中插入和删除项目必须是 O (log n) 操作。这就是优先级队列的全部意义所在。在将元素添加到优先级队列时调用“排序”绝对是荒谬的,并且会完全扼杀你的表现。
【讨论】:
以上是关于swift中的优先队列的主要内容,如果未能解决你的问题,请参考以下文章