5 4 1 使用堆演算法實現優級佇列

2021-07-09 12:03:11 字數 1573 閱讀 7551

乙個優先順序佇列通常是使用堆演算法來實現,實現優先順序佇列主要困難有以下幾點:

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開始,要...