1*46c4c49dSIbrahim Kanouche// Copyright 2017 Google Inc. 2*46c4c49dSIbrahim Kanouche// 3*46c4c49dSIbrahim Kanouche// Licensed under the Apache License, Version 2.0 (the "License"); 4*46c4c49dSIbrahim Kanouche// you may not use this file except in compliance with the License. 5*46c4c49dSIbrahim Kanouche// You may obtain a copy of the License at 6*46c4c49dSIbrahim Kanouche// 7*46c4c49dSIbrahim Kanouche// http://www.apache.org/licenses/LICENSE-2.0 8*46c4c49dSIbrahim Kanouche// 9*46c4c49dSIbrahim Kanouche// Unless required by applicable law or agreed to in writing, software 10*46c4c49dSIbrahim Kanouche// distributed under the License is distributed on an "AS IS" BASIS, 11*46c4c49dSIbrahim Kanouche// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12*46c4c49dSIbrahim Kanouche// See the License for the specific language governing permissions and 13*46c4c49dSIbrahim Kanouche// limitations under the License. 14*46c4c49dSIbrahim Kanouche 15*46c4c49dSIbrahim Kanouche// Package pq provides a priority queue. 16*46c4c49dSIbrahim Kanouchepackage pq 17*46c4c49dSIbrahim Kanouche 18*46c4c49dSIbrahim Kanoucheimport "container/heap" 19*46c4c49dSIbrahim Kanouche 20*46c4c49dSIbrahim Kanouche// NewQueue returns an unbounded priority queue that compares elements using 21*46c4c49dSIbrahim Kanouche// less; the minimal element is at the top of the queue. 22*46c4c49dSIbrahim Kanouche// 23*46c4c49dSIbrahim Kanouche// If setIndex is not nil, the queue calls setIndex to inform each element of 24*46c4c49dSIbrahim Kanouche// its position in the queue. If an element's priority changes, its position in 25*46c4c49dSIbrahim Kanouche// the queue may be incorrect. Call Fix on the element's index to update the 26*46c4c49dSIbrahim Kanouche// queue. Call Remove on the element's index to remove it from the queue. 27*46c4c49dSIbrahim Kanouchefunc NewQueue(less func(x, y interface{}) bool, setIndex func(x interface{}, idx int)) *Queue { 28*46c4c49dSIbrahim Kanouche return &Queue{ 29*46c4c49dSIbrahim Kanouche heap: pqHeap{ 30*46c4c49dSIbrahim Kanouche less: less, 31*46c4c49dSIbrahim Kanouche setIndex: setIndex, 32*46c4c49dSIbrahim Kanouche }, 33*46c4c49dSIbrahim Kanouche } 34*46c4c49dSIbrahim Kanouche} 35*46c4c49dSIbrahim Kanouche 36*46c4c49dSIbrahim Kanouche// Queue is a priority queue that supports updating the priority of an element. 37*46c4c49dSIbrahim Kanouche// A Queue must be created with NewQueue. 38*46c4c49dSIbrahim Kanouchetype Queue struct { 39*46c4c49dSIbrahim Kanouche heap pqHeap 40*46c4c49dSIbrahim Kanouche} 41*46c4c49dSIbrahim Kanouche 42*46c4c49dSIbrahim Kanouche// Len returns the number of elements in the queue. 43*46c4c49dSIbrahim Kanouchefunc (pq *Queue) Len() int { 44*46c4c49dSIbrahim Kanouche return pq.heap.Len() 45*46c4c49dSIbrahim Kanouche} 46*46c4c49dSIbrahim Kanouche 47*46c4c49dSIbrahim Kanouche// Push adds x to the queue. 48*46c4c49dSIbrahim Kanouchefunc (pq *Queue) Push(x interface{}) { 49*46c4c49dSIbrahim Kanouche heap.Push(&pq.heap, x) 50*46c4c49dSIbrahim Kanouche} 51*46c4c49dSIbrahim Kanouche 52*46c4c49dSIbrahim Kanouche// Min returns the minimal element. 53*46c4c49dSIbrahim Kanouche// Min panics if the queue is empty. 54*46c4c49dSIbrahim Kanouchefunc (pq *Queue) Min() interface{} { 55*46c4c49dSIbrahim Kanouche return pq.heap.a[0] 56*46c4c49dSIbrahim Kanouche} 57*46c4c49dSIbrahim Kanouche 58*46c4c49dSIbrahim Kanouche// Pop removes and returns the minimal element. 59*46c4c49dSIbrahim Kanouche// Pop panics if the queue is empty. 60*46c4c49dSIbrahim Kanouchefunc (pq *Queue) Pop() interface{} { 61*46c4c49dSIbrahim Kanouche return heap.Pop(&pq.heap) 62*46c4c49dSIbrahim Kanouche} 63*46c4c49dSIbrahim Kanouche 64*46c4c49dSIbrahim Kanouche// Fix adjusts the heap to reflect that the element at index has changed priority. 65*46c4c49dSIbrahim Kanouchefunc (pq *Queue) Fix(index int) { 66*46c4c49dSIbrahim Kanouche heap.Fix(&pq.heap, index) 67*46c4c49dSIbrahim Kanouche} 68*46c4c49dSIbrahim Kanouche 69*46c4c49dSIbrahim Kanouche// Remove removes the element at index i from the heap. 70*46c4c49dSIbrahim Kanouchefunc (pq *Queue) Remove(index int) { 71*46c4c49dSIbrahim Kanouche heap.Remove(&pq.heap, index) 72*46c4c49dSIbrahim Kanouche} 73*46c4c49dSIbrahim Kanouche 74*46c4c49dSIbrahim Kanouche// pqHeap implements heap.Interface. 75*46c4c49dSIbrahim Kanouchetype pqHeap struct { 76*46c4c49dSIbrahim Kanouche a []interface{} 77*46c4c49dSIbrahim Kanouche less func(x, y interface{}) bool 78*46c4c49dSIbrahim Kanouche setIndex func(x interface{}, idx int) 79*46c4c49dSIbrahim Kanouche} 80*46c4c49dSIbrahim Kanouche 81*46c4c49dSIbrahim Kanouchefunc (h pqHeap) Len() int { 82*46c4c49dSIbrahim Kanouche return len(h.a) 83*46c4c49dSIbrahim Kanouche} 84*46c4c49dSIbrahim Kanouche 85*46c4c49dSIbrahim Kanouchefunc (h pqHeap) Less(i, j int) bool { 86*46c4c49dSIbrahim Kanouche return h.less(h.a[i], h.a[j]) 87*46c4c49dSIbrahim Kanouche} 88*46c4c49dSIbrahim Kanouche 89*46c4c49dSIbrahim Kanouchefunc (h pqHeap) Swap(i, j int) { 90*46c4c49dSIbrahim Kanouche h.a[i], h.a[j] = h.a[j], h.a[i] 91*46c4c49dSIbrahim Kanouche if h.setIndex != nil { 92*46c4c49dSIbrahim Kanouche h.setIndex(h.a[i], i) 93*46c4c49dSIbrahim Kanouche h.setIndex(h.a[j], j) 94*46c4c49dSIbrahim Kanouche } 95*46c4c49dSIbrahim Kanouche} 96*46c4c49dSIbrahim Kanouche 97*46c4c49dSIbrahim Kanouchefunc (h *pqHeap) Push(x interface{}) { 98*46c4c49dSIbrahim Kanouche n := len(h.a) 99*46c4c49dSIbrahim Kanouche if h.setIndex != nil { 100*46c4c49dSIbrahim Kanouche h.setIndex(x, n) 101*46c4c49dSIbrahim Kanouche } 102*46c4c49dSIbrahim Kanouche h.a = append(h.a, x) 103*46c4c49dSIbrahim Kanouche} 104*46c4c49dSIbrahim Kanouche 105*46c4c49dSIbrahim Kanouchefunc (h *pqHeap) Pop() interface{} { 106*46c4c49dSIbrahim Kanouche old := h.a 107*46c4c49dSIbrahim Kanouche n := len(old) 108*46c4c49dSIbrahim Kanouche x := old[n-1] 109*46c4c49dSIbrahim Kanouche h.a = old[:n-1] 110*46c4c49dSIbrahim Kanouche return x 111*46c4c49dSIbrahim Kanouche} 112