码迷,mamicode.com
首页 > 编程语言 > 详细

5.4.1 使用堆算法实现优级队列

时间:2016-01-17 11:03:15      阅读:180      评论:0      收藏:0      [点我收藏+]

标签:

一个优先级队列通常是使用堆算法来实现,实现优先级队列主要困难有以下几点:

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 深圳

5.4.1 使用堆算法实现优级队列

标签:

原文地址:http://blog.csdn.net/caimouse/article/details/50531108

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!