pax_global_header00006660000000000000000000000064140036365450014520gustar00rootroot0000000000000052 comment=c2e3d577e1fdb4eefcbf7bf60db76f0b2e256b97 tinyqueue-0.1.1/000077500000000000000000000000001400363654500135475ustar00rootroot00000000000000tinyqueue-0.1.1/LICENSE000066400000000000000000000013561400363654500145610ustar00rootroot00000000000000ISC License Copyright (c) 2017, Vladimir Agafonkin Permission to use, copy, modify, and/or distribute this software for any purpose with or without fee is hereby granted, provided that the above copyright notice and this permission notice appear in all copies. THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. tinyqueue-0.1.1/README.md000066400000000000000000000004731400363654500150320ustar00rootroot00000000000000# tinyqueue GoDoc tinyqueue is a Go package for binary heap priority queues. Ported from the [tinyqueue](https://github.com/mourner/tinyqueue) Javascript library. tinyqueue-0.1.1/go.mod000066400000000000000000000000551400363654500146550ustar00rootroot00000000000000module github.com/tidwall/tinyqueue go 1.15 tinyqueue-0.1.1/tinyqueue.go000066400000000000000000000024641400363654500161340ustar00rootroot00000000000000package tinyqueue type Queue struct { length int data []Item } type Item interface { Less(Item) bool } func New(data []Item) *Queue { q := &Queue{} q.data = data q.length = len(data) if q.length > 0 { i := q.length >> 1 for ; i >= 0; i-- { q.down(i) } } return q } func (q *Queue) Push(item Item) { q.data = append(q.data, item) q.length++ q.up(q.length - 1) } func (q *Queue) Pop() Item { if q.length == 0 { return nil } top := q.data[0] q.length-- if q.length > 0 { q.data[0] = q.data[q.length] q.down(0) } q.data = q.data[:len(q.data)-1] return top } func (q *Queue) Peek() Item { if q.length == 0 { return nil } return q.data[0] } func (q *Queue) Len() int { return q.length } func (q *Queue) down(pos int) { data := q.data halfLength := q.length >> 1 item := data[pos] for pos < halfLength { left := (pos << 1) + 1 right := left + 1 best := data[left] if right < q.length && data[right].Less(best) { left = right best = data[right] } if !best.Less(item) { break } data[pos] = best pos = left } data[pos] = item } func (q *Queue) up(pos int) { data := q.data item := data[pos] for pos > 0 { parent := (pos - 1) >> 1 current := data[parent] if !item.Less(current) { break } data[pos] = current pos = parent } data[pos] = item } tinyqueue-0.1.1/tinyqueue_test.go000066400000000000000000000026041400363654500171670ustar00rootroot00000000000000package tinyqueue import ( "math/rand" "reflect" "sort" "testing" "time" ) type floatValue float64 func assertEqual(t *testing.T, a, b interface{}) { if !reflect.DeepEqual(a, b) { t.Fatalf("'%v' != '%v'", a, b) } } func (a floatValue) Less(b Item) bool { return a < b.(floatValue) } var data, sorted = func() ([]Item, []Item) { rand.Seed(time.Now().UnixNano()) var data []Item for i := 0; i < 100; i++ { data = append(data, floatValue(rand.Float64()*100)) } sorted := make([]Item, len(data)) copy(sorted, data) sort.Slice(sorted, func(i, j int) bool { return sorted[i].Less(sorted[j]) }) return data, sorted }() func TestMaintainsPriorityQueue(t *testing.T) { q := New(nil) for i := 0; i < len(data); i++ { q.Push(data[i]) } assertEqual(t, q.Peek(), sorted[0]) var result []Item for q.length > 0 { result = append(result, q.Pop()) } assertEqual(t, result, sorted) } func TestAcceptsDataInConstructor(t *testing.T) { q := New(data) var result []Item for q.length > 0 { result = append(result, q.Pop()) } assertEqual(t, result, sorted) } func TestHandlesEdgeCasesWithFewElements(t *testing.T) { q := New(nil) q.Push(floatValue(2)) q.Push(floatValue(1)) q.Pop() q.Pop() q.Pop() q.Push(floatValue(2)) q.Push(floatValue(1)) assertEqual(t, float64(q.Pop().(floatValue)), 1.0) assertEqual(t, float64(q.Pop().(floatValue)), 2.0) assertEqual(t, q.Pop(), nil) }