forked from TrueCloudLab/rclone
vendor: add github.com/aalpar/deheap
This commit is contained in:
parent
4c82b1f3c6
commit
84369286df
6 changed files with 268 additions and 0 deletions
20
vendor/github.com/aalpar/deheap/LICENSE.txt
generated
vendored
Normal file
20
vendor/github.com/aalpar/deheap/LICENSE.txt
generated
vendored
Normal file
|
@ -0,0 +1,20 @@
|
|||
Copyright 2019 Aaron H. Alpar
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining
|
||||
a copy of this software and associated documentation files
|
||||
(the "Software"), to deal in the Software without restriction,
|
||||
including without limitation the rights to use, copy, modify, merge,
|
||||
publish, distribute, sublicense, and/or sell copies of the Software,
|
||||
and to permit persons to whom the Software is furnished to do so,
|
||||
subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included
|
||||
in all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
||||
IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
|
||||
CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
|
||||
TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
|
||||
SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
14
vendor/github.com/aalpar/deheap/README.md
generated
vendored
Normal file
14
vendor/github.com/aalpar/deheap/README.md
generated
vendored
Normal file
|
@ -0,0 +1,14 @@
|
|||
# deheap
|
||||
|
||||
Package deheap provides the implementation of a doubly ended heap.
|
||||
Doubly ended heaps are heaps with two sides, a min side and a max side.
|
||||
Like normal single-sided heaps, elements can be pushed onto and pulled
|
||||
off of a deheap. deheaps have an additional `Pop` function, `PopMax`, that
|
||||
returns elements from the opposite side of the ordering.
|
||||
|
||||
This implementation has emphasized compatibility with existing libraries
|
||||
in the sort and heap packages.
|
||||
|
||||
Performace of the deheap functions should be very close to the
|
||||
performance of the functions of the heap library
|
||||
|
228
vendor/github.com/aalpar/deheap/deheap.go
generated
vendored
Normal file
228
vendor/github.com/aalpar/deheap/deheap.go
generated
vendored
Normal file
|
@ -0,0 +1,228 @@
|
|||
//
|
||||
// Copyright 2019 Aaron H. Alpar
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining
|
||||
// a copy of this software and associated documentation files
|
||||
// (the "Software"), to deal in the Software without restriction,
|
||||
// including without limitation the rights to use, copy, modify, merge,
|
||||
// publish, distribute, sublicense, and/or sell copies of the Software,
|
||||
// and to permit persons to whom the Software is furnished to do so,
|
||||
// subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included
|
||||
// in all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
||||
// IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
|
||||
// CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
|
||||
// TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
|
||||
// SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
//
|
||||
|
||||
//
|
||||
// Package deheap provides the implementation of a doubly ended heap.
|
||||
// Doubly ended heaps are heaps with two sides, a min side and a max side.
|
||||
// Like normal single-sided heaps, elements can be pushed onto and pulled
|
||||
// off of a deheap. deheaps have an additional Pop function, PopMax, that
|
||||
// returns elements from the opposite side of the ordering.
|
||||
//
|
||||
// This implementation has emphasized compatibility with existing libraries
|
||||
// in the sort and heap packages.
|
||||
//
|
||||
// Performace of the deheap functions should be very close to the
|
||||
// performance of the functions of the heap library
|
||||
//
|
||||
package deheap
|
||||
|
||||
import (
|
||||
"container/heap"
|
||||
"math/bits"
|
||||
)
|
||||
|
||||
func hparent(i int) int {
|
||||
return (i - 1) / 2
|
||||
}
|
||||
|
||||
func hlchild(i int) int {
|
||||
return (i * 2) + 1
|
||||
}
|
||||
|
||||
func parent(i int) int {
|
||||
return ((i + 1) / 4) - 1
|
||||
}
|
||||
|
||||
func lchild(i int) int {
|
||||
return ((i + 1 ) * 4) - 1
|
||||
}
|
||||
|
||||
func level(i int) int {
|
||||
return bits.Len(uint(i)+1) - 1
|
||||
}
|
||||
|
||||
func isMinHeap(i int) bool {
|
||||
return level(i) % 2 == 0
|
||||
}
|
||||
|
||||
func min4(h heap.Interface, l int, min bool, i int) int {
|
||||
q := i
|
||||
i++
|
||||
if i >= l {
|
||||
return q
|
||||
}
|
||||
if min == h.Less(i, q) {
|
||||
q = i
|
||||
}
|
||||
i++
|
||||
if i >= l {
|
||||
return q
|
||||
}
|
||||
if min == h.Less(i, q) {
|
||||
q = i
|
||||
}
|
||||
i++
|
||||
if i >= l {
|
||||
return q
|
||||
}
|
||||
if min == h.Less(i, q) {
|
||||
q = i
|
||||
}
|
||||
return q
|
||||
}
|
||||
|
||||
// min2
|
||||
func min2(h heap.Interface, l int, min bool, i int) int {
|
||||
if i+1 >= l {
|
||||
return i
|
||||
}
|
||||
if min != h.Less(i+1, i) {
|
||||
return i
|
||||
}
|
||||
return i + 1
|
||||
}
|
||||
|
||||
// min3
|
||||
func min3(h heap.Interface, l int, min bool, i, j, k int) int {
|
||||
q := i
|
||||
if j < l && h.Less(j, q) == min {
|
||||
q = j
|
||||
}
|
||||
if k < l && h.Less(k, q) == min {
|
||||
q = k
|
||||
}
|
||||
return q
|
||||
}
|
||||
|
||||
// bubbledown
|
||||
func bubbledown(h heap.Interface, l int, min bool, i int) (q int, r int) {
|
||||
q = i
|
||||
r = i
|
||||
for {
|
||||
// find min of children
|
||||
j := min2(h, l, min, hlchild(i))
|
||||
if j >= l {
|
||||
break
|
||||
}
|
||||
// find min of grandchildren
|
||||
k := min4(h, l, min, lchild(i))
|
||||
// swap of less than the element at i
|
||||
v := min3(h, l, min, i, j, k)
|
||||
if v == i || v >= l {
|
||||
break
|
||||
}
|
||||
// v == k
|
||||
q = v
|
||||
h.Swap(v, i)
|
||||
if v == j {
|
||||
break
|
||||
}
|
||||
p := hparent(v)
|
||||
if h.Less(p, v) == min {
|
||||
h.Swap(p, v)
|
||||
r = p
|
||||
}
|
||||
i = v
|
||||
}
|
||||
return q, r
|
||||
}
|
||||
|
||||
// bubbleup
|
||||
func bubbleup(h heap.Interface, min bool, i int) (q bool) {
|
||||
if i < 0 {
|
||||
return false
|
||||
}
|
||||
j := parent(i)
|
||||
for j >= 0 && min == h.Less(i, j) {
|
||||
q = true
|
||||
h.Swap(i, j)
|
||||
i = j
|
||||
j = parent(i)
|
||||
}
|
||||
min = !min
|
||||
j = hparent(i)
|
||||
for j >= 0 && min == h.Less(i, j) {
|
||||
q = true
|
||||
h.Swap(i, j)
|
||||
i = j
|
||||
j = parent(i)
|
||||
}
|
||||
return q
|
||||
}
|
||||
|
||||
// Pop the smallest value off the heap. See heap.Pop().
|
||||
// Time complexity is O(log n), where n = h.Len()
|
||||
func Pop(h heap.Interface) interface{} {
|
||||
l := h.Len()-1
|
||||
h.Swap(0, l)
|
||||
q := h.Pop()
|
||||
bubbledown(h, l, true, 0)
|
||||
return q
|
||||
}
|
||||
|
||||
// Pop the largest value off the heap. See heap.Pop().
|
||||
// Time complexity is O(log n), where n = h.Len()
|
||||
func PopMax(h heap.Interface) interface{} {
|
||||
l := h.Len()
|
||||
j := 0
|
||||
if l > 1 {
|
||||
j = min2(h, l,false, 1)
|
||||
}
|
||||
l = l - 1
|
||||
h.Swap(j, l)
|
||||
q := h.Pop()
|
||||
bubbledown(h, l,false, j)
|
||||
return q
|
||||
}
|
||||
|
||||
// Remove element at index i. See heap.Remove().
|
||||
// The complexity is O(log n) where n = h.Len().
|
||||
func Remove(h heap.Interface, i int) (q interface{}) {
|
||||
l := h.Len() - 1
|
||||
h.Swap(i, l)
|
||||
q = h.Pop()
|
||||
if l != i {
|
||||
q, r := bubbledown(h, l, isMinHeap(i), i)
|
||||
bubbleup(h, isMinHeap(q), q)
|
||||
bubbleup(h, isMinHeap(r), r)
|
||||
}
|
||||
return q
|
||||
}
|
||||
|
||||
// Push an element onto the heap. See heap.Push()
|
||||
// Time complexity is O(log n), where n = h.Len()
|
||||
func Push(h heap.Interface, o interface{}) {
|
||||
h.Push(o)
|
||||
l := h.Len()
|
||||
i := l - 1
|
||||
bubbleup(h, isMinHeap(i), i)
|
||||
}
|
||||
|
||||
// Init initializes the heap.
|
||||
// This should be called once on non-empty heaps before calling Pop(), PopMax() or Push(). See heap.Init()
|
||||
func Init(h heap.Interface) {
|
||||
l := h.Len()
|
||||
for i := 0; i < l; i++ {
|
||||
bubbleup(h, isMinHeap(i), i)
|
||||
}
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue