forked from gree/futurama
-
Notifications
You must be signed in to change notification settings - Fork 0
/
priority_queue.go
147 lines (125 loc) · 3.22 KB
/
priority_queue.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
package futurama
import (
"container/heap"
)
type HeapItem struct {
// public
Value interface{}
// private
priority int64
index int
}
func NewHeapItem(priority int64, value interface{}) *HeapItem {
return &HeapItem{value, priority, -1}
}
type CompareFunc func(a *HeapItem, b *HeapItem) bool
type Heap struct {
items []*HeapItem
compare CompareFunc
}
func NewHeap(reversed bool) *Heap {
var compare CompareFunc
if reversed {
compare = func(a *HeapItem, b *HeapItem) bool { return a.priority > b.priority }
} else {
compare = func(a *HeapItem, b *HeapItem) bool { return a.priority < b.priority }
}
return &Heap{make([]*HeapItem, 0), compare}
}
func (self *Heap) Len() int { return len(self.items) }
func (self *Heap) Less(i, j int) bool {
return self.compare(self.items[i], self.items[j])
}
func (self *Heap) Swap(i, j int) {
self.items[i], self.items[j] = self.items[j], self.items[i]
self.items[i].index = i
self.items[j].index = j
}
func (self *Heap) Push(x interface{}) {
n := len(self.items)
item := x.(*HeapItem)
item.index = n
self.items = append(self.items, item)
}
func (self *Heap) Pop() interface{} {
n := len(self.items)
item := self.items[n-1]
item.index = -1 // for safety
self.items = self.items[:n-1]
return item
}
type PQItem interface {
GetKey() string
}
type PQ struct {
maxSize int
heap *Heap
lookupMap map[string]*HeapItem
}
func NewPQ(reversed bool, maxSize int) *PQ {
return &PQ{
maxSize: maxSize,
heap: NewHeap(reversed),
lookupMap: make(map[string]*HeapItem),
}
}
func (self *PQ) Top() PQItem {
if self.Len() == 0 {
return nil
}
return self.heap.items[0].Value.(PQItem)
}
// meanings of returned values
// index >= 0, poped == nil: queue is not full, new item has been pushed
// index >= 0, poped != nil: queue is full, new item has been pushed, the item with lowest priority has been poped
// index < 0, poped == nil: not possible for PQ (only if there is a wrong usage/implementation e.g. we set max == 0 ...)
// index < 0, poped != nil: queue is full, new item has not been pushed because it has the lowest priority
func (self *PQ) Push(value PQItem, priority int64) (index int, poped PQItem) {
index = -1
poped = nil
key := value.GetKey()
if idx := self.Lookup(key); idx >= 0 {
return
}
item := NewHeapItem(priority, value)
len := self.heap.Len()
if len == self.maxSize {
if len > 0 && self.heap.compare(self.heap.items[0], item) {
poped = heap.Pop(self.heap).(*HeapItem).Value.(PQItem)
delete(self.lookupMap, poped.GetKey())
} else {
return
}
}
heap.Push(self.heap, item)
index = item.index
self.lookupMap[key] = item
return
}
func (self *PQ) Pop() PQItem {
if self.heap.Len() == 0 {
return nil
}
poped := heap.Pop(self.heap).(*HeapItem).Value.(PQItem)
delete(self.lookupMap, poped.GetKey())
return poped
}
func (self *PQ) Remove(key string) PQItem {
if item, ok := self.lookupMap[key]; ok {
if removed := heap.Remove(self.heap, item.index); removed != nil {
delete(self.lookupMap, key)
return removed.(*HeapItem).Value.(PQItem)
}
}
return nil
}
func (self *PQ) Lookup(key string) int {
if item, ok := self.lookupMap[key]; ok {
return item.index
} else {
return -1
}
}
func (self *PQ) Len() int {
return self.heap.Len()
}