堆積是一種集合,它隨時都知道自己最小的項目,並讓你快速取出該項目。它是優先佇列的天然工具,優先佇列是一種等待隊伍,下一個被服務的是最重要的項目,而不是等最久的那個。堆積位於 heaps 詞彙中。
<min-heap> 會建立一個空堆積,其中最小的鍵會最先出來;<max-heap> 則是它的鏡像。
<min-heap> ( -- min-heap )
<max-heap> ( -- max-heap )
每個項目都以一個值搭配一個鍵的形式儲存,鍵就是 Factor 用來排序的優先順序。heap-push 可以加入一個項目:
heap-push ( value key heap -- )
USING: heaps ;
<min-heap>
"alice" 5 pick heap-push ! value "alice", priority 5
"bob" 2 pick heap-push ! value "bob", priority 2
堆積是可變的:heap-push 會直接就地修改它,而不是回傳一個新的堆積。在 heap-push 消耗掉堆積之後,keep 很方便用來把堆積放回堆疊上。
heap-peek 會回傳最前面的項目,也就是鍵最小的值,而且不會將它移除。heap-pop 會回傳該項目,並將它移除。heap-empty? 會回報是否還有剩下項目,讓你知道什麼時候該停止取出。heap-pop-all 會一次移除所有項目,並依優先順序回傳一份由 { key value } 配對組成的關聯串列。
heap-peek ( heap -- value key )
heap-pop ( heap -- value key )
heap-empty? ( heap -- ? )
heap-pop-all ( heap -- alist )
USING: assocs heaps kernel prettyprint ;
<min-heap>
"alice" 5 pick heap-push
"bob" 2 pick heap-push
dup heap-empty? . ! => f (two items waiting)
dup heap-peek drop . ! => "bob" (smallest key, still in the heap)
dup heap-pop drop . ! => "bob" (smallest key, now removed)
heap-pop-all . ! => { { 5 "alice" } }
heap-pop 和 heap-empty? 是一次處理一個項目的基礎元件,先查看或取出最前面的項目,對它採取動作,然後在 heap-empty? 回傳 t 之後停下來。下面的任務會用 heap-pop-all 一口氣清空整個佇列,不過只要持續取出直到堆積變空,也會得到相同的順序。
heap-pop-all 產生的配對是一份關聯串列:values(位於 assocs 中)只保留值,捨棄鍵。
一家繁忙的銀行依照優先順序服務等待的顧客,而不是依照他們抵達的順序。每位顧客在取號時會拿到一個優先順序號碼,而櫃員總是接著服務號碼最小的那位(1 最為急迫)。最小堆積就是最完美的等候隊伍。
定義 new-queue,不接受任何引數,並回傳一個全新的空優先佇列。
new-queue
! => an empty priority queue
定義 join-queue,接受顧客名稱、優先順序號碼和一個佇列。它會把顧客加入佇列並回傳該佇列,因此可以一個接一個地加入顧客。
new-queue "alice" 5 rot join-queue "bob" 2 rot join-queue
! => the queue, now holding alice (5) and bob (2)
定義 next-name,接受一個佇列,回傳下一個應該被服務的顧客名稱,也就是優先順序號碼最小的那位,而且不會將這位顧客移除。
new-queue "alice" 5 rot join-queue "bob" 2 rot join-queue next-name .
! => "bob"
定義 serve-all,接受一個佇列,回傳所有等待中顧客的名稱,並依照他們會被服務的順序排列。
new-queue "alice" 5 rot join-queue "bob" 2 rot join-queue
"carol" 9 rot join-queue serve-all .
! => { "bob" "alice" "carol" }