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
|
language: go
|
||||||
|
|
||||||
go:
|
go:
|
||||||
- "1.8"
|
|
||||||
- "1.9"
|
- "1.9"
|
||||||
- "1.10"
|
- "1.10"
|
||||||
- "1.11"
|
- "1.11"
|
||||||
|
- "1.12"
|
||||||
- "tip"
|
- "tip"
|
||||||
|
|
||||||
before_script:
|
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.
|
// Deque represents a single instance of the deque data structure.
|
||||||
type Deque struct {
|
type Deque struct {
|
||||||
buf []interface{}
|
buf []interface{}
|
||||||
head int
|
head int
|
||||||
tail int
|
tail int
|
||||||
count 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.
|
// 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.
|
// growIfFull resizes up if the buffer is full.
|
||||||
func (q *Deque) growIfFull() {
|
func (q *Deque) growIfFull() {
|
||||||
if len(q.buf) == 0 {
|
if len(q.buf) == 0 {
|
||||||
q.buf = make([]interface{}, minCapacity)
|
if q.minCap == 0 {
|
||||||
|
q.minCap = minCapacity
|
||||||
|
}
|
||||||
|
q.buf = make([]interface{}, q.minCap)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
if q.count == len(q.buf) {
|
if q.count == len(q.buf) {
|
||||||
|
@ -201,7 +216,7 @@ func (q *Deque) growIfFull() {
|
||||||
|
|
||||||
// shrinkIfExcess resize down if the buffer 1/4 full.
|
// shrinkIfExcess resize down if the buffer 1/4 full.
|
||||||
func (q *Deque) shrinkIfExcess() {
|
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()
|
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()) {
|
func assertPanics(t *testing.T, name string, f func()) {
|
||||||
defer func() {
|
defer func() {
|
||||||
if r := recover(); r == nil {
|
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
|
// 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
|
// 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
|
// insert(Len(),e) is the same as PushBack(e). Complexity is constant plus
|
||||||
|
|
Loading…
Reference in a new issue