5.4.1 使用堆算法实现优级队列
2016-01-17 10:28
274 查看
一个优先级队列通常是使用堆算法来实现,实现优先级队列主要困难有以下几点:
1)排序的稳定性:怎么样实现两个优级一样的任务时返回最先添加的任务?
2)在元组比较里,如果(优先级,任务)对相同时,就没有比较的顺序了。
3)如果一个任务的优先级改变了,你怎么样把它移动到堆的一个新位置上?
4)当任务删除时,你怎么样发现它是删除的,并且把它从堆队列里删除?
为了解决前面两个问题,采用三个元素的列表来实现,这个列表包括:优先级、入口计数、任务。入口计数就是当任务添加时分配一个增加的数字,以便知道任务是添加的顺序,这样就可以解决任务优先级相同时,可以返回最先添加的任务。同时由于入口计数不一样,不用比较到任务,就已经判断出来任务优先顺序了。
剩下来的问题,就是找到未曾执行的任务,并且修改它的优先级,或者完全删除它。查找任务可以通过字典来实现,这个字典保存指向任务列表。删除一个任务或者改变优先级都会让任务队列的堆排序不稳定,因此采用标记的方法来删除,并没有实际删除相关的任务。
例子:
#python 3.4
import heapq
import itertools
pq = [] # 保存堆排序的列表
entry_finder = {} # 保存任务查找的字典
REMOVED = '<removed-task>' # 任务删除的标记
counter = itertools.count() # 产生任务入口顺序的计数
def add_task(task, priority=0):
'添加任务或者更新任务的优先级'
if task in entry_finder:
remove_task(task)
count = next(counter)
entry = [priority, count, task]
entry_finder[task] = entry
heapq.heappush(pq, entry)
def remove_task(task):
'标记一个存在的任务删除:REMOVED. 如果不存在抛出异常KeyError'
entry = entry_finder.pop(task)
entry[-1] = REMOVED
def pop_task():
'删除已经标记删除的任务,并返回最低优先级的任务. 如果不存在抛出KeyError'
while pq:
priority, count, task = heapq.heappop(pq)
if task is not REMOVED:
del entry_finder[task]
return task
raise KeyError('pop from an empty priority queue')
add_task('abc', 5)
add_task('b', 1)
add_task('c', 2)
add_task('bb', 1)
print(pop_task())
print(pop_task())
print(pop_task())
结果输出如下:
b
bb
c
蔡军生 QQ:9073204 深圳
1)排序的稳定性:怎么样实现两个优级一样的任务时返回最先添加的任务?
2)在元组比较里,如果(优先级,任务)对相同时,就没有比较的顺序了。
3)如果一个任务的优先级改变了,你怎么样把它移动到堆的一个新位置上?
4)当任务删除时,你怎么样发现它是删除的,并且把它从堆队列里删除?
为了解决前面两个问题,采用三个元素的列表来实现,这个列表包括:优先级、入口计数、任务。入口计数就是当任务添加时分配一个增加的数字,以便知道任务是添加的顺序,这样就可以解决任务优先级相同时,可以返回最先添加的任务。同时由于入口计数不一样,不用比较到任务,就已经判断出来任务优先顺序了。
剩下来的问题,就是找到未曾执行的任务,并且修改它的优先级,或者完全删除它。查找任务可以通过字典来实现,这个字典保存指向任务列表。删除一个任务或者改变优先级都会让任务队列的堆排序不稳定,因此采用标记的方法来删除,并没有实际删除相关的任务。
例子:
#python 3.4
import heapq
import itertools
pq = [] # 保存堆排序的列表
entry_finder = {} # 保存任务查找的字典
REMOVED = '<removed-task>' # 任务删除的标记
counter = itertools.count() # 产生任务入口顺序的计数
def add_task(task, priority=0):
'添加任务或者更新任务的优先级'
if task in entry_finder:
remove_task(task)
count = next(counter)
entry = [priority, count, task]
entry_finder[task] = entry
heapq.heappush(pq, entry)
def remove_task(task):
'标记一个存在的任务删除:REMOVED. 如果不存在抛出异常KeyError'
entry = entry_finder.pop(task)
entry[-1] = REMOVED
def pop_task():
'删除已经标记删除的任务,并返回最低优先级的任务. 如果不存在抛出KeyError'
while pq:
priority, count, task = heapq.heappop(pq)
if task is not REMOVED:
del entry_finder[task]
return task
raise KeyError('pop from an empty priority queue')
add_task('abc', 5)
add_task('b', 1)
add_task('c', 2)
add_task('bb', 1)
print(pop_task())
print(pop_task())
print(pop_task())
结果输出如下:
b
bb
c
蔡军生 QQ:9073204 深圳
相关文章推荐
- Hier block添加参数
- Data Binding Guide——google官方文档翻译(下)
- 5.4.1 使用堆算法实现优级队列
- 【转】Delphi+Halcon实战一:两行代码识别QR二维码
- GreenPlumn数据库体系结构
- HDU_1000
- GPIO
- 事件处理
- IOS视图控制对象生命周期
- Halcon的应用程序 打开后 弹出没有帮助文件错误提示
- 学习C++,重新做做ACM
- centos 6 安装docker
- 电流转电压几种电路&nbsp;&lt;转&gt;
- 数字表示的电容
- 学习笔记:12864液晶模块的…
- 王小谟:领航人生
- 理解stm32&nbsp;bit-band映射公式【转】
- FFT算法在单片机中的使用&amp;&amp;L…
- C中的volatile用法[转]
- STM32&nbsp;重定义printf导致无法…