資料結構與演算法 優先佇列

2021-10-04 21:32:23 字數 3592 閱讀 9625

優先佇列按照佇列的方式正常入隊,但按照優先順序出隊。有兩種實現方式:(二插堆、多項式堆等等)和二叉搜尋樹。這裡重點講解二叉堆,關於二叉搜尋樹的內容見這篇文章。

堆是一種特殊的完全二叉樹。大根堆:完全二叉樹的任一節點都比其孩子節點大。小根堆:完全二叉樹的任一節點都比其孩子節點小。堆的向下調整:假設根節點的左右子樹都是堆,但根節點不滿足堆的性質,可以通過一次向下調整將其變成乙個堆。因為二叉堆是完全二叉樹,一般可以用陣列來表示,這樣不會浪費空間。大根堆和小根堆的舉例如下所示:

用陣列表示的二叉堆,有如下性質:

二叉堆的時間複雜度:

python實現:heapq

import heapq

# 將array列表轉為堆的結構

heap.heapify(array)

# 彈出堆中的最小值

# 往堆中插入新值a

heapq.heapreplace(array, a)

# 獲得array中前k個最大的值

heapq.nlargest(k, array)

# 獲得array中前k個最小的值

heapq.nsmallest(k, array)

此題為leetcode第23題

合併 k 個排序鍊錶,返回合併後的排序鍊錶。

import heapq

class

solution

:def

mergeklists

(self, lists: list[listnode])-

> listnode:

head = p = listnode(0)

# 建立堆

a =for i in

range

(len

(lists)):

if lists[i]

:# 元組在heapq裡比較的機制是從元組首位0開始,即遇到相同,就比較元組下一位

# 比如(1,2), (1,3),前者比後者小。

# 這題剛好node值有重複的,同時listnode無法被比較,所以會報錯

(lists[i]

.val, i)

) lists[i]

= lists[i]

.next

while a:

p.next

= listnode(val)

p = p.

next

if lists[idx]

:(lists[idx]

.val, idx)

) lists[idx]

= lists[idx]

.next

return head.

next

此題為leetcode第215題
import heapq

class

solution

:def

findkthlargest

(self, nums: list[

int]

, k:

int)

->

int:

n =len(nums)

# 建立含k個元素的小根堆

temp =

for i in

range

(k):

)# 遍歷nums裡剩下的元素,比堆頂大的話更新小根堆

for i in

range

(k, n)

: top = temp[0]

if nums[i]

> top:

heapq.heapreplace(temp, nums[i]

)# 最後結果為堆頂元素

return temp[

0]

此題為leetcode第347題

思路:首先利用雜湊表統計nums裡的元素num出現的頻率。然後建立大小為k的小根堆heap,heap列表中的元素為元組,包含num及其頻率。堆滿後,若新加的數大於堆頂元素的頻率,則heapreplace堆頂元素。最後heap裡包含的就是前k個高頻元素。

import heapq

class

solution

:def

topkfrequent

(self, nums: list[

int]

, k:

int)

-> list[

int]

:# 統計元素出現頻率

hash

=for num in nums:

hash

[num]

=hash

.get(num,0)

+1heap =

for num, freq in

hash

.items():

iflen

(heap)

== k:

if heap[0]

[0]< freq:

heapq.heapreplace(heap,

(freq, num)

)else

:(freq, num)

) res =

while heap:[1

])return res

此題為leetcode第703題

設計乙個找到資料流中第k大元素的類(class)。注意是排序後的第k大元素,不是第k個不同的元素。你的 kthlargest 類需要乙個同時接收整數 k 和整數陣列nums 的構造器,它包含資料流中的初始元素。每次呼叫 kthlargest.add,返回當前資料流中第k大的元素。

import heapq

class

kthlargest

:def

__init__

(self, k:

int, nums: list[

int]):

self.nums = nums

self.k = k

heapq.heapify(self.nums)

# 留下k個元素,即前k大的

while

len(self.nums)

> k:

defadd

(self, val:

int)

->

int:

iflen

(self.nums)

< self.k:

elif self.nums[0]

< val:

# 新的值更大則更新

heapq.heapreplace(self.nums, val)

return self.nums[

0]

資料結構與演算法 優先佇列

英雄聯盟遊戲裡面防禦塔都有乙個自動攻擊功能,小兵排著隊進入防禦塔的攻擊範圍,防禦塔先攻擊靠得最近的小兵,這時候大炮車的優先順序更高 因為系統判定大炮車對於防禦塔的威脅更大 所以防禦塔會優先攻擊大炮車。而當大炮車陣亡,剩下的全部都是普通小兵,這時候離得近的優先順序越高,防禦塔優先攻擊距離更近的小兵。優...

資料結構與演算法 複習 堆 優先佇列

插入演算法 該演算法從優先佇列的序列去觀察,比較直觀。首先把要插入的元素放在隊尾temp裡。從佇列的最後乙個元素,逐次向前尋找父節點,空位隨之移動,當到達隊頭,或者當前元素小於temp元素時,即可插入。刪除演算法 刪除最小元素,也就是最頭的元素。當我們利用 當前元素數量 1 這樣的操作刪除元素後,最...

資料結構與演算法 堆 的優先佇列

作業系統核心作業排程是優先佇列的乙個應用例項,它根據優先順序的高低而不是先到先服務的方 式來進行排程 如果最小鍵值元素擁有最高的優先順序,那麼這種優先佇列叫作公升序優先佇列 即總是先刪除最小 的元素 類似的,如果最大鍵值元素擁有最高的優先順序,那麼這種優先佇列叫作降序優先佇列 即總是先刪除最大的元素...