New func to specify minimum capacity
A larger minimum capacity can be specified to avoid buffer resizing in cases where the size frequently grows and shrinks across a wide range. Add module support
This commit is contained in:
parent
c892bbebe0
commit
2ff0cd8822
|
@ -1,10 +1,10 @@
|
|||
language: go
|
||||
|
||||
go:
|
||||
- "1.8"
|
||||
- "1.9"
|
||||
- "1.10"
|
||||
- "1.11"
|
||||
- "1.12"
|
||||
- "tip"
|
||||
|
||||
before_script:
|
||||
|
|
27
deque.go
27
deque.go
|
@ -6,10 +6,22 @@ const minCapacity = 16
|
|||
|
||||
// Deque represents a single instance of the deque data structure.
|
||||
type Deque struct {
|
||||
buf []interface{}
|
||||
head int
|
||||
tail int
|
||||
count int
|
||||
buf []interface{}
|
||||
head int
|
||||
tail int
|
||||
count int
|
||||
minCap int
|
||||
}
|
||||
|
||||
// New creates a new Deque that has a minimum capacity of 2^minCapacityExp. If
|
||||
// the value of the minimum capacity is less than or equal to the minimum
|
||||
// allowed, then New returns the same as new(Deque).
|
||||
func New(minCapacityExp uint) *Deque {
|
||||
q := new(Deque)
|
||||
if 1<<minCapacityExp > minCapacity {
|
||||
q.minCap = 1 << minCapacityExp
|
||||
}
|
||||
return q
|
||||
}
|
||||
|
||||
// Len returns the number of elements currently stored in the queue.
|
||||
|
@ -191,7 +203,10 @@ func (q *Deque) next(i int) int {
|
|||
// growIfFull resizes up if the buffer is full.
|
||||
func (q *Deque) growIfFull() {
|
||||
if len(q.buf) == 0 {
|
||||
q.buf = make([]interface{}, minCapacity)
|
||||
if q.minCap == 0 {
|
||||
q.minCap = minCapacity
|
||||
}
|
||||
q.buf = make([]interface{}, q.minCap)
|
||||
return
|
||||
}
|
||||
if q.count == len(q.buf) {
|
||||
|
@ -201,7 +216,7 @@ func (q *Deque) growIfFull() {
|
|||
|
||||
// shrinkIfExcess resize down if the buffer 1/4 full.
|
||||
func (q *Deque) shrinkIfExcess() {
|
||||
if len(q.buf) > minCapacity && (q.count<<2) == len(q.buf) {
|
||||
if len(q.buf) > q.minCap && (q.count<<2) == len(q.buf) {
|
||||
q.resize()
|
||||
}
|
||||
}
|
||||
|
|
|
@ -480,6 +480,25 @@ func TestRemoveOutOfRangePanics(t *testing.T) {
|
|||
})
|
||||
}
|
||||
|
||||
func TestNew(t *testing.T) {
|
||||
exp := uint(8)
|
||||
q := New(8)
|
||||
q.PushBack("A")
|
||||
if q.minCap != 1<<exp {
|
||||
t.Fatal("wrong minimum capacity")
|
||||
}
|
||||
if len(q.buf) != 1<<exp {
|
||||
t.Fatal("wrong buffer size")
|
||||
}
|
||||
q.PopBack()
|
||||
if q.minCap != 1<<exp {
|
||||
t.Fatal("wrong minimum capacity")
|
||||
}
|
||||
if len(q.buf) != 1<<exp {
|
||||
t.Fatal("wrong buffer size")
|
||||
}
|
||||
}
|
||||
|
||||
func assertPanics(t *testing.T, name string, f func()) {
|
||||
defer func() {
|
||||
if r := recover(); r == nil {
|
||||
|
@ -558,6 +577,30 @@ func BenchmarkRemove(b *testing.B) {
|
|||
}
|
||||
}
|
||||
|
||||
func BenchmarkYoyo(b *testing.B) {
|
||||
var q Deque
|
||||
for i := 0; i < b.N; i++ {
|
||||
for j := 0; j < 65536; j++ {
|
||||
q.PushBack(j)
|
||||
}
|
||||
for j := 0; j < 65536; j++ {
|
||||
q.PopFront()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func BenchmarkYoyoFixed(b *testing.B) {
|
||||
q := New(16)
|
||||
for i := 0; i < b.N; i++ {
|
||||
for j := 0; j < 65536; j++ {
|
||||
q.PushBack(j)
|
||||
}
|
||||
for j := 0; j < 65536; j++ {
|
||||
q.PopFront()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// insert is used to insert an element into the middle of the queue, before the
|
||||
// element at the specified index. insert(0,e) is the same as PushFront(e) and
|
||||
// insert(Len(),e) is the same as PushBack(e). Complexity is constant plus
|
||||
|
|
Loading…
Reference in a new issue