├── .travis.yml ├── license ├── pqueue.go ├── pqueue_test.go └── readme.md /.travis.yml: -------------------------------------------------------------------------------- 1 | language: go 2 | 3 | go: 4 | - 1.4 5 | 6 | before_install: 7 | - go get -v golang.org/x/tools/cmd/vet 8 | - go get -v golang.org/x/tools/cmd/cover 9 | - go get -v github.com/golang/lint/golint 10 | 11 | install: 12 | - go install -race -v std 13 | - go get -race -t -v ./... 14 | - go install -race -v ./... 15 | 16 | script: 17 | - go vet ./... 18 | - $HOME/gopath/bin/golint . 19 | - go test -cpu=2 -race -v ./... 20 | - go test -cpu=2 -covermode=atomic ./... 21 | -------------------------------------------------------------------------------- /license: -------------------------------------------------------------------------------- 1 | Copyright 2013 Facebook, Inc 2 | 3 | Licensed under the Apache License, Version 2.0 (the "License"); 4 | you may not use this file except in compliance with the License. 5 | You may obtain a copy of the License at 6 | 7 | http://www.apache.org/licenses/LICENSE-2.0 8 | 9 | Unless required by applicable law or agreed to in writing, software 10 | distributed under the License is distributed on an "AS IS" BASIS, 11 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | See the License for the specific language governing permissions and 13 | limitations under the License. 14 | -------------------------------------------------------------------------------- /pqueue.go: -------------------------------------------------------------------------------- 1 | // Package pqueue provides a priority queue implementation. 2 | package pqueue 3 | 4 | import ( 5 | "container/heap" 6 | ) 7 | 8 | // Item in the PriorityQueue. 9 | type Item struct { 10 | Value interface{} 11 | Priority int64 12 | Index int 13 | } 14 | 15 | // PriorityQueue as implemented by a min heap 16 | // ie. the 0th element is the *lowest* value. 17 | type PriorityQueue []*Item 18 | 19 | // New creates a PriorityQueue of the given capacity. 20 | func New(capacity int) PriorityQueue { 21 | if capacity <= 0 { 22 | capacity = 1 23 | } 24 | return make(PriorityQueue, 0, capacity) 25 | } 26 | 27 | // Len returns the length of the queue. 28 | func (pq PriorityQueue) Len() int { 29 | return len(pq) 30 | } 31 | 32 | // Less returns true if the item at index i has a lower priority than the item 33 | // at index j. 34 | func (pq PriorityQueue) Less(i, j int) bool { 35 | return pq[i].Priority < pq[j].Priority 36 | } 37 | 38 | // Swap the items at index i and j. 39 | func (pq PriorityQueue) Swap(i, j int) { 40 | pq[i], pq[j] = pq[j], pq[i] 41 | pq[i].Index = i 42 | pq[j].Index = j 43 | } 44 | 45 | // Push a new value to the queue. 46 | func (pq *PriorityQueue) Push(x interface{}) { 47 | n := len(*pq) 48 | c := cap(*pq) 49 | if n+1 > c { 50 | npq := make(PriorityQueue, n, c*2) 51 | copy(npq, *pq) 52 | *pq = npq 53 | } 54 | *pq = (*pq)[0 : n+1] 55 | item := x.(*Item) 56 | item.Index = n 57 | (*pq)[n] = item 58 | } 59 | 60 | // Pop an item from the queue. 61 | func (pq *PriorityQueue) Pop() interface{} { 62 | n := len(*pq) 63 | c := cap(*pq) 64 | if n < (c/4) && c > 25 { 65 | npq := make(PriorityQueue, n, c/2) 66 | copy(npq, *pq) 67 | *pq = npq 68 | } 69 | item := (*pq)[n-1] 70 | item.Index = -1 71 | *pq = (*pq)[0 : n-1] 72 | return item 73 | } 74 | 75 | // PeekAndShift based the max priority. 76 | func (pq *PriorityQueue) PeekAndShift(max int64) (*Item, int64) { 77 | if pq.Len() == 0 { 78 | return nil, 0 79 | } 80 | 81 | item := (*pq)[0] 82 | if item.Priority > max { 83 | return nil, item.Priority - max 84 | } 85 | heap.Remove(pq, 0) 86 | 87 | return item, 0 88 | } 89 | -------------------------------------------------------------------------------- /pqueue_test.go: -------------------------------------------------------------------------------- 1 | package pqueue 2 | 3 | import ( 4 | "container/heap" 5 | "math/rand" 6 | "sort" 7 | "testing" 8 | 9 | "github.com/facebookgo/ensure" 10 | ) 11 | 12 | func TestPriorityQueue(t *testing.T) { 13 | c := 100 14 | pq := New(c) 15 | 16 | for i := 0; i < c+1; i++ { 17 | heap.Push(&pq, &Item{Value: i, Priority: int64(i)}) 18 | } 19 | ensure.DeepEqual(t, pq.Len(), c+1) 20 | ensure.DeepEqual(t, cap(pq), c*2) 21 | 22 | for i := 0; i < c+1; i++ { 23 | item := heap.Pop(&pq) 24 | ensure.DeepEqual(t, item.(*Item).Value.(int), i) 25 | } 26 | ensure.DeepEqual(t, cap(pq), c/4) 27 | } 28 | 29 | func TestUnsortedInsert(t *testing.T) { 30 | c := 100 31 | pq := New(c) 32 | ints := make([]int, 0, c) 33 | 34 | for i := 0; i < c; i++ { 35 | v := rand.Int() 36 | ints = append(ints, v) 37 | heap.Push(&pq, &Item{Value: i, Priority: int64(v)}) 38 | } 39 | ensure.DeepEqual(t, pq.Len(), c) 40 | ensure.DeepEqual(t, cap(pq), c) 41 | 42 | sort.Sort(sort.IntSlice(ints)) 43 | 44 | for i := 0; i < c; i++ { 45 | item, _ := pq.PeekAndShift(int64(ints[len(ints)-1])) 46 | ensure.DeepEqual(t, item.Priority, int64(ints[i])) 47 | } 48 | } 49 | 50 | func TestRemove(t *testing.T) { 51 | c := 100 52 | pq := New(c) 53 | 54 | for i := 0; i < c; i++ { 55 | v := rand.Int() 56 | heap.Push(&pq, &Item{Value: "test", Priority: int64(v)}) 57 | } 58 | 59 | for i := 0; i < 10; i++ { 60 | heap.Remove(&pq, rand.Intn((c-1)-i)) 61 | } 62 | 63 | lastPriority := heap.Pop(&pq).(*Item).Priority 64 | for i := 0; i < (c - 10 - 1); i++ { 65 | item := heap.Pop(&pq) 66 | ensure.DeepEqual(t, lastPriority < item.(*Item).Priority, true) 67 | lastPriority = item.(*Item).Priority 68 | } 69 | } 70 | 71 | func TestPriorityQueueWithZeroCapacity(t *testing.T) { 72 | pq := New(0) 73 | ensure.DeepEqual(t, cap(pq), 1) 74 | } 75 | -------------------------------------------------------------------------------- /readme.md: -------------------------------------------------------------------------------- 1 | pqueue [![Build Status](https://secure.travis-ci.org/facebookgo/pqueue.png)](https://travis-ci.org/facebookgo/pqueue) 2 | ====== 3 | 4 | Priority queue from: 5 | https://github.com/mreiferson/go-httpclient/tree/go11_11/pqueue 6 | 7 | Documentation: 8 | https://godoc.org/github.com/facebookgo/pqueue 9 | --------------------------------------------------------------------------------