乙個優先順序佇列通常是使用堆演算法來實現,實現優先順序佇列主要困難有以下幾點:
1)排序的穩定性:怎麼樣實現兩個優級一樣的任務時返回最先新增的任務?
2)在元組比較裡,如果(優先順序,任務)對相同時,就沒有比較的順序了。
3)如果乙個任務的優先順序改變了,你怎麼樣把它移動到堆的乙個新位置上?
4)當任務刪除時,你怎麼樣發現它是刪除的,並且把它從堆佇列裡刪除?
為了解決前面兩個問題,採用三個元素的列表來實現,這個列表包括:優先順序、入口計數、任務。入口計數就是當任務新增時分配乙個增加的數字,以便知道任務是新增的順序,這樣就可以解決任務優先順序相同時,可以返回最先新增的任務。同時由於入口計數不一樣,不用比較到任務,就已經判斷出來任務優先順序了。
剩下來的問題,就是找到未曾執行的任務,並且修改它的優先順序,或者完全刪除它。查詢任務可以通過字典來實現,這個字典儲存指向任務列表。刪除乙個任務或者改變優先順序都會讓任務佇列的堆排序不穩定,因此採用標記的方法來刪除,並沒有實際刪除相關的任務。
例子:#python 3.4
import heapq
import itertools
pq = # 儲存堆排序的列表
entry_finder = {} # 儲存任務查詢的字典
removed = '' # 任務刪除的標記
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
def remove_task(task):
'標記乙個存在的任務刪除:
removed.
如果不存在丟擲異常
keyerror'
entry = entry_finder.pop(task)
entry[-1] = removed
def pop_task():
'刪除已經標記刪除的任務,並返回最低優先順序的任務
. 如果不存在丟擲
keyerror'
while 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())
結果輸出如下:bbb
c
演算法入門 優先佇列實現 堆
優先佇列 priorityqueue 根據key值的大小將元素進行排序 先被pop的通常是優先順序最高的。此處介紹基於堆實現的優先佇列,binary heap是一種完全二叉樹,以大堆為例,每棵樹的根節點的key值一定大於其子孫節點的key值,完全二叉樹除了最底層的葉子節點外,其他位置都是填滿的。這樣...
堆實現最優佇列
最優佇列就是靠堆實現的,普通的佇列是一種先進先出的資料結構,元素在佇列尾追加,而從佇列頭刪除。在優先佇列中,元素被賦予優先順序。當訪問元素時,具有最高優先順序的元素最先刪除。優先佇列具有最高端先出 largest in,first out 的行為特徵。也就最優佇列可以保證隊頭一定是有限度最大的元素。...
用堆實現優先佇列
堆的性質 1.乙個是他是乙個陣列 當然你也可以真的用鍊錶來做。2.他可以看做乙個完全二叉樹。注意是完全二叉樹。所以他的葉子個數剛好是nsize 2個。3.我使用的下標從1開始,這樣好算,如果節點的位置為i,他的父節點就是i 2,他的左孩子結點就是i 2,右孩子結點就是i 2 1,如果下標從0開始,要...