@@ -24,10 +24,7 @@ would be easier to solve.
2424
2525package queue
2626
27- import (
28- "sort"
29- "sync"
30- )
27+ import "sync"
3128
3229// Item is an item that can be added to the priority queue.
3330type Item interface {
@@ -42,50 +39,66 @@ type Item interface {
4239
4340type priorityItems []Item
4441
42+ func (items * priorityItems ) swap (i , j int ) {
43+ (* items )[i ], (* items )[j ] = (* items )[j ], (* items )[i ]
44+ }
45+
46+ func (items * priorityItems ) pop () Item {
47+ size := len (* items )
48+
49+ // Move last leaf to root, and 'pop' the last item.
50+ items .swap (size - 1 , 0 )
51+ item := (* items )[size - 1 ] // Item to return.
52+ * items = (* items )[:size - 1 ]
53+
54+ // 'Bubble down' to restore heap property.
55+ index := 0
56+ childL , childR := 2 * index + 1 , 2 * index + 2
57+ for len (* items ) > childL {
58+ child := childL
59+ if len (* items ) > childR && (* items )[childR ].Compare ((* items )[childL ]) < 0 {
60+ child = childR
61+ }
62+
63+ if (* items )[child ].Compare ((* items )[index ]) < 0 {
64+ items .swap (index , child )
65+
66+ index = child
67+ childL , childR = 2 * index + 1 , 2 * index + 2
68+ } else {
69+ break
70+ }
71+ }
72+
73+ return item
74+ }
75+
4576func (items * priorityItems ) get (number int ) []Item {
4677 returnItems := make ([]Item , 0 , number )
47- index := 0
4878 for i := 0 ; i < number ; i ++ {
4979 if i >= len (* items ) {
5080 break
5181 }
5282
53- returnItems = append (returnItems , (* items )[i ])
54- (* items )[i ] = nil
55- index ++
83+ returnItems = append (returnItems , items .pop ())
5684 }
5785
58- * items = (* items )[index :]
5986 return returnItems
6087}
6188
62- func (items * priorityItems ) insert (item Item ) {
63- if len (* items ) == 0 {
64- * items = append (* items , item )
65- return
66- }
89+ func (items * priorityItems ) push (item Item ) {
90+ // Stick the item as the end of the last level.
91+ * items = append (* items , item )
6792
68- equalFound := false
69- i := sort .Search (len (* items ), func (i int ) bool {
70- result := (* items )[i ].Compare (item )
71- if result == 0 {
72- equalFound = true
73- }
74- return result >= 0
75- })
93+ // 'Bubble up' to restore heap property.
94+ index := len (* items ) - 1
95+ parent := int ((index - 1 ) / 2 )
96+ for parent >= 0 && (* items )[parent ].Compare (item ) > 0 {
97+ items .swap (index , parent )
7698
77- if equalFound {
78- return
99+ index = parent
100+ parent = int (( index - 1 ) / 2 )
79101 }
80-
81- if i == len (* items ) {
82- * items = append (* items , item )
83- return
84- }
85-
86- * items = append (* items , nil )
87- copy ((* items )[i + 1 :], (* items )[i :])
88- (* items )[i ] = item
89102}
90103
91104// PriorityQueue is similar to queue except that it takes
@@ -94,6 +107,7 @@ func (items *priorityItems) insert(item Item) {
94107type PriorityQueue struct {
95108 waiters waiters
96109 items priorityItems
110+ itemMap map [Item ]bool
97111 lock sync.Mutex
98112 disposeLock sync.Mutex
99113 disposed bool
@@ -112,7 +126,10 @@ func (pq *PriorityQueue) Put(items ...Item) error {
112126 }
113127
114128 for _ , item := range items {
115- pq .items .insert (item )
129+ if ok := pq .itemMap [item ]; ! ok {
130+ pq .itemMap [item ] = true
131+ pq .items .push (item )
132+ }
116133 }
117134
118135 for {
@@ -149,6 +166,11 @@ func (pq *PriorityQueue) Get(number int) ([]Item, error) {
149166 }
150167
151168 var items []Item
169+ defer func () {
170+ for _ , item := range items {
171+ pq .itemMap [item ] = false
172+ }
173+ }()
152174
153175 if len (pq .items ) == 0 {
154176 sema := newSema ()
@@ -230,6 +252,7 @@ func (pq *PriorityQueue) Dispose() {
230252// NewPriorityQueue is the constructor for a priority queue.
231253func NewPriorityQueue (hint int ) * PriorityQueue {
232254 return & PriorityQueue {
233- items : make (priorityItems , 0 , hint ),
255+ items : make (priorityItems , 0 , hint ),
256+ itemMap : make (map [Item ]bool , hint ),
234257 }
235258}
0 commit comments