- iOS/Objective-C 元类和类别
- objective-c - -1001 错误,当 NSURLSession 通过 httpproxy 和/etc/hosts
- java - 使用网络类获取 url 地址
- ios - 推送通知中不播放声音
我有一个调度算法,我比较优先级/任务元组列表的最小值和最大值,对它们执行一些更改优先级的操作,然后将它们重新插入到列表中,并适当地更新列表。heapq是最好的数据结构吗?如何在不弹出的情况下进行初始比较(基本上是确定优先级值是否相距足够远,需要进一步操作;如果不是,函数将停止)?一旦做了比较,我将如何把最大值和最小值放在一起,因为heapq是专为弹出最小值而设计的?
最佳答案
heapq
只提供一个最小堆,也就是说,您可以在o(log n)时间内弹出min
值,但不能弹出max
值。
如果需要类似于heapq
的双面数据结构,有几个基本选项。
首先,常规最小堆有什么问题不仅仅是api;找到最大值需要O(n)
时间而不是O(1)
时间,因此弹出它需要O(n)
而不是O(log n)
,这是您需要改进的关键。
一个简单的技巧是保留两个堆,一个具有正常值,一个具有修饰的正常值,以便它们向后排序下面是伪代码的实现:
def push(self, value):
insert into both normal and reversed heaps
def minpop(self):
check that the min value of normal hasn't reached the min value of reversed
pop and return the min value of normal
def maxpop(self):
check that the min value of reversed hasn't reached the min value of normal
pop and return the min value of reversed
normal
和
reversed
版本交错到一个结构中,使得在上面的“check”情况下很容易做正确的事情(而不是留下值)。
bintrees
和
skiplist
这样的东西,它们都应该有效。
blist
。它使用平衡树和数组的特殊混合,而不是经过仔细研究的数据结构,乍一看可能会让您觉得它不太可信。不过,我相信它比任何竞争模块都得到更多的使用和实际测试,而且它也得到了相当大的优化。(当您处理
A * log Bn + C
性能时,更改
A
或
C
通常比更改
B
有更大的影响)实际上它还有一个很好的界面,其中一些界面如果您使用
blist.sortedlist
,您只需执行
sl[0]
、
sl[-1]
、
sl.pop(0)
、
sl.pop(-1)
和
sl.add(x)
,几乎与您预期的完全一样。
class MyQueue(object):
def __init__(self):
self.sl = blist.sortedlist(key=operator.itemgetter(0))
def add(self, priority, task):
self.sl.add((priority, task))
def step(self):
if self.sl[-1][0] - self.sl[0][0] < MyQueue.EPSILON:
return
minprio, mintask = self.sl.pop(0)
maxprio, maxtask = self.sl.pop(-1)
newminprio, newmaxprio = recalc_priorities(minprio, maxprio)
self.add(newminprio, mintask)
self.add(newmaxprio, maxtask)
O(log N)
而不是
O(1)
但是,如果您只需要执行这些操作,那么有一个简单的方法:将这些值缓存起来:
class MyQueue(object):
def __init__(self):
self.sl = blist.sortedlist(key=operator.itemgetter(0))
self.minprio, self.maxprio = None, None
def add(self, priority, task):
self.sl.add((priority, task))
if prio < self.minprio: self.minprio = prio
elif prio > self.maxprio: self.maxprio = prio
def step(self):
if self.maxprio - self.minprio < MyQueue.EPSILON:
return
minprio, mintask = self.sl.pop(0)
maxprio, maxtask = self.sl.pop(-1)
newminprio, newmaxprio = recalc_priorities(minprio, maxprio)
self.add(newminprio, mintask)
self.add(newmaxprio, maxtask)
self.minprio, self.maxprio = sl[0][0], sl[-1][0]
step
O(1)
而不是
O(log n)
的快速路径,并使所有现有的
O(log n)
操作仍然
O(log n)
。
O(n)
的方法都足够好,所以您应该只使用最简单的实现并完成它。但有时(特别是对于许多手术,但是很小的
n
,或者数据不典型的情况),常数因子、最佳情况等会产生巨大的差异。在这种情况下,正确的做法是构建多个实现并使用真实数据进行测试,看看什么是最快的。
关于python - 与Mines和Maxes合作-Heapq合适吗?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/14248692/
我注意到给定一个列表,如果我使用 heapq.heapify() 创建一个堆,元素的顺序与我在列表上迭代并执行 heap.heappush() 时获得的顺序不同。 谁能帮我理解为什么? 此外,对于可迭
我正在尝试使用 Python 的 heapq 来实现 Dijkstra 的算法。如果发现通往它的较短路径,则该算法需要更改单元格的值。 我正在通过此检查执行此操作: if curr_cell[0] +
来自官方heapq的示例: >>> heap = [] >>> data = [(1, 'J'), (4, 'N'), (3, 'H'), (2, 'O')] >>> for item in data
工具.py import heapq class PriorityQueue: def __init__(self): self.heap=[] def push(se
我有相当多的 n=10000 个排序列表,每个列表的长度为 k=100。由于合并两个排序列表需要线性时间,我认为在深度为 log(n) 的树中递归合并长度为 O(nk) 的排序列表与 heapq.me
我是 python 的新手(使用 v3.x 语法),希望得到有关 heapq 与排序的复杂性和性能的说明。 我已经为贪婪的“找到最佳工作安排”算法实现了基于 heapq 的解决方案。但后来我了解了将“
我的问题来自下面leetcode中的解决方案,我不明白为什么是O(k+(n-k)log(k))。 补充:可能复杂度不是这个,其实我不知道heappush()和heappop()的时间复杂度 # O(k
我正在尝试使用自定义排序谓词构建堆。由于进入它的值是“用户定义”类型,我无法修改它们的内置比较谓词。 有没有办法做类似的事情: h = heapq.heapify([...], key=my_lt_p
>>> from heapq import heappush >>> heap = [] >>> heappush(heap,(0,{"k":0})) >>> heappush(heap,(0,{"k
首先,我阅读了这个SO question但它实际上不包括我想要的方法。此外,否定实际值不适用于我的用例。 Heapq 文档:https://docs.python.org/3.6/library/he
我正在使用 heapq 对象来存储我实现的类的对象。 import heapq heap = [] element1 = Element('A', 1) element2 = Element('B',
我试图在我的程序中使用 Python 模块 heapq,但我在使用 heapq.heappop() 时遇到了一个奇怪的问题。该函数似乎没有返回堆中的最小元素。看看下面的代码: Python 2.7.1
我有一本包含 {key: count} 的字典,比如说status_count = {'管理分析':13859,'计算机程序员':72112}我正在尝试为 heapq.nlargest() 编写一个键
我最初尝试使用优先级队列编写算法来解决 15 题,但我的导师告诉我们,我们需要编写 a* 实现,并建议我们使用 heapq 而不是优先级队列。我无法找到我的 heapq 的长度/大小,也无法访问我的
我将一个名为 UNVISITED 的空列表转换为一个堆,这样: UNVISITED = [] heapq.heappush(UNVISITED, (a.f, a)) 我推送的对象a,是从一个类中实例化
如果堆化此 [(10,'Mike'),(20,'Jack'),(10,'Bob')] 并返回堆的最小值,它会保证返回 (10,'Mike') 而不是 (10,'Bob') 吗? 最佳答案 no hea
每次 heapq.heapify 函数更改我的堆列表中的元素时,我都希望得到回调通知(顺便说一句,这是跟踪列表中的对象以及它们的索引如何获取所需要的改变了)。 我的计划是从 list 继承并重写 __
如何返回可迭代的第n大项的原始列表中的索引 heapq.nlargest(2, [100, 2, 400, 500, 400]) output = [(3,500), (2, 400)] 这已经花费了
我正在使用 Python 的 heapq 模块按升序和降序获取数据。 对于升序,我使用的是最小堆,它运行良好,如下所示: >>> from heapq import heapify, heappop
我希望拥有一堆对象,而不仅仅是数字。它们将具有堆可以排序的整数属性。在python中使用堆最简单的方法是heapq,但是在使用heapq时如何告诉它按特定属性排序呢? 最佳答案 根据 document
我是一名优秀的程序员,十分优秀!