github.com/igggame/nebulas-go@v2.1.0+incompatible/common/pdeque/pdeque.go (about) 1 package pdeque 2 3 import ( 4 "math" 5 "sync" 6 ) 7 8 // Less is compare function for elements in queue 9 type Less func(a interface{}, b interface{}) bool 10 11 // PriorityDeque is a priority double-ended queue 12 type PriorityDeque struct { 13 less Less 14 heap []interface{} 15 mu sync.Mutex 16 } 17 18 // LvTy is type of level 19 type LvTy int 20 21 // LvMin & LvMax in priority double-ended queue 22 const ( 23 LvMin LvTy = iota 24 LvMax 25 ) 26 27 // NewPriorityDeque create a new PriorityDeque 28 func NewPriorityDeque(less Less) *PriorityDeque { 29 return &PriorityDeque{ 30 less: less, 31 } 32 } 33 34 // Len return the length of the priority deque 35 func (q *PriorityDeque) Len() int { 36 return len(q.heap) 37 } 38 39 // Insert an item into priority deque 40 func (q *PriorityDeque) Insert(ele interface{}) { 41 q.mu.Lock() 42 defer q.mu.Unlock() 43 44 q.heap = append(q.heap, ele) 45 q.bubbleUp(q.Len() - 1) 46 } 47 48 // Max return the max value in priority deque 49 func (q *PriorityDeque) Max() interface{} { 50 q.mu.Lock() 51 defer q.mu.Unlock() 52 53 heap := q.heap 54 pos := 0 55 switch q.Len() { 56 case 0: 57 return nil 58 case 1: 59 break 60 case 2: 61 pos = 1 62 break 63 default: 64 pos = 1 65 if q.less(heap[1], heap[2]) { 66 pos = 2 67 } 68 break 69 } 70 tx := heap[pos] 71 return tx 72 } 73 74 // PopMax pop the max value in priority deque 75 func (q *PriorityDeque) PopMax() interface{} { 76 q.mu.Lock() 77 defer q.mu.Unlock() 78 79 heap := q.heap 80 pos := 0 81 switch q.Len() { 82 case 0: 83 return nil 84 case 1: 85 break 86 case 2: 87 pos = 1 88 break 89 default: 90 pos = 1 91 if q.less(heap[1], heap[2]) { 92 pos = 2 93 } 94 break 95 } 96 tx := heap[pos] 97 q.deleteAt(pos) 98 return tx 99 } 100 101 // PopMin pop the min value in priority deque 102 func (q *PriorityDeque) PopMin() interface{} { 103 q.mu.Lock() 104 defer q.mu.Unlock() 105 106 if q.Len() > 0 { 107 tx := q.heap[0] 108 q.deleteAt(0) 109 return tx 110 } 111 return nil 112 } 113 114 // Min return the min value in priority deque 115 func (q *PriorityDeque) Min() interface{} { 116 q.mu.Lock() 117 defer q.mu.Unlock() 118 119 if q.Len() > 0 { 120 tx := q.heap[0] 121 return tx 122 } 123 return nil 124 } 125 126 func (q *PriorityDeque) deleteAt(pos int) { 127 heap := q.heap 128 size := len(heap) 129 heap[pos] = heap[size-1] 130 q.heap = heap[0 : size-1] 131 q.trickleDown(pos) 132 } 133 134 func level(pos int) LvTy { 135 level := (int)(math.Floor(math.Log2((float64)(pos + 1)))) 136 if level%2 == 0 { 137 return LvMin 138 } 139 return LvMax 140 } 141 142 func parent(pos int) int { 143 return (pos - 1) / 2 144 } 145 146 func leftChildren(pos int) int { 147 return pos*2 + 1 148 } 149 150 func rightChildren(pos int) int { 151 return pos*2 + 2 152 } 153 154 func (q *PriorityDeque) swap(i int, j int) { 155 q.heap[i], q.heap[j] = q.heap[j], q.heap[i] 156 } 157 158 func (q *PriorityDeque) bubbleUp(pos int) { 159 heap := q.heap 160 switch level(pos) { 161 case LvMin: 162 if pos > 0 { 163 if q.less(heap[parent(pos)], heap[pos]) { 164 q.swap(pos, parent(pos)) 165 q.bubbleUpMax(parent(pos)) 166 } else { 167 q.bubbleUpMin(pos) 168 } 169 } 170 break 171 case LvMax: 172 if pos > 0 { 173 if q.less(heap[pos], heap[parent(pos)]) { 174 q.swap(pos, parent(pos)) 175 q.bubbleUpMin(parent(pos)) 176 } else { 177 q.bubbleUpMax(pos) 178 } 179 } 180 break 181 } 182 } 183 184 func (q *PriorityDeque) bubbleUpMin(pos int) { 185 heap := q.heap 186 grandParent := parent(parent(pos)) 187 if pos > 2 { 188 if q.less(heap[pos], heap[grandParent]) { 189 q.swap(pos, grandParent) 190 q.bubbleUpMin(grandParent) 191 } 192 } 193 } 194 195 func (q *PriorityDeque) bubbleUpMax(pos int) { 196 heap := q.heap 197 grandParent := parent(parent(pos)) 198 if pos > 2 { 199 if q.less(heap[grandParent], heap[pos]) { 200 q.swap(pos, grandParent) 201 q.bubbleUpMax(grandParent) 202 } 203 } 204 } 205 206 func (q *PriorityDeque) trickleDown(pos int) { 207 switch level(pos) { 208 case LvMin: 209 q.trickleDownMin(pos) 210 break 211 case LvMax: 212 q.trickleDownMax(pos) 213 break 214 } 215 } 216 217 func (q *PriorityDeque) children(parents []int) []int { 218 heap := q.heap 219 size := len(heap) 220 res := []int{} 221 for _, pos := range parents { 222 if leftChildren(pos) < size { 223 res = append(res, leftChildren(pos)) 224 } 225 if rightChildren(pos) < size { 226 res = append(res, rightChildren(pos)) 227 } 228 } 229 return res 230 } 231 232 func (q *PriorityDeque) sort(items []int) []int { 233 heap := q.heap 234 for i := 0; i < len(items); i++ { 235 for j := i + 1; j < len(items); j++ { 236 if q.less(heap[items[j]], heap[items[i]]) { 237 items[i], items[j] = items[j], items[i] 238 } 239 } 240 } 241 return items 242 } 243 244 func (q *PriorityDeque) trickleDownMin(pos int) { 245 heap := q.heap 246 children := q.children([]int{pos}) 247 if len(children) > 0 { 248 grandchild := q.children(children) 249 if len(grandchild) > 0 { 250 children = append(children, grandchild...) 251 opts := q.sort(children) 252 opt := opts[0] 253 if q.less(heap[opt], heap[pos]) { 254 q.swap(opt, pos) 255 if q.less(heap[parent(opt)], heap[pos]) { 256 q.swap(opt, parent(opt)) 257 } 258 q.trickleDownMin(opt) 259 } 260 } else { 261 opts := q.sort(children) 262 opt := opts[0] 263 if q.less(heap[opt], heap[pos]) { 264 q.swap(opt, pos) 265 } 266 } 267 } 268 } 269 270 func (q *PriorityDeque) trickleDownMax(pos int) { 271 heap := q.heap 272 children := q.children([]int{pos}) 273 if len(children) > 0 { 274 grandchild := q.children(children) 275 if len(grandchild) > 0 { 276 children = append(children, grandchild...) 277 opts := q.sort(children) 278 opt := opts[len(opts)-1] 279 if q.less(heap[pos], heap[opt]) { 280 q.swap(opt, pos) 281 if q.less(heap[opt], heap[parent(opt)]) { 282 q.swap(opt, parent(opt)) 283 } 284 q.trickleDownMax(opt) 285 } 286 } else { 287 opts := q.sort(children) 288 opt := opts[len(opts)-1] 289 if q.less(heap[pos], heap[opt]) { 290 q.swap(opt, pos) 291 } 292 } 293 } 294 }