Add At() method

This commit is contained in:
Andrew Gillis 2018-05-10 19:11:55 -04:00
parent a91677b1e1
commit 7d7061a1b6
2 changed files with 85 additions and 17 deletions

View file

@ -129,6 +129,27 @@ func (q *Deque) Back() interface{} {
return q.buf[q.prev(q.tail)]
}
// Get returns the element at index i in the queue without removing the element
// from the queue. This method accepts only non-negative index values. get(0)
// refers to the first element and is the same as Front(). get(Len()-1) refers
// to the last element and is the same as Back(). If the index is invalid, the
// call panics.
//
// The purpose of Get is to allow Deque to serve as a more general purpose
// circular buffer, such as an LRU cache or a circular log. For such uses,
// items are only added to and removed from the the ends of the deque, but may
// be read from any place within the deque. Consider the case of a circular
// log buffer, where new entries are pushed on one end and the oldest entries
// are popped from the other end, and any/all of the entries in the buffer must
// be readable without altering the buffer contents.
func (q *Deque) At(i int) interface{} {
if i < 0 || i >= q.count {
panic("deque: Get() called with index out of range")
}
// bitwise modulus
return q.buf[(q.head+i)&(len(q.buf)-1)]
}
// Clear removes all elements from the queue, but retains the current capacity.
// This is useful when repeatedly reusing the queue at high frequency to avoid
// GC during reuse. The queue will not be resized smaller as long as items are

View file

@ -211,7 +211,7 @@ func checkRotate(t *testing.T, size int) {
for i := 0; i < q.Len(); i++ {
x := i
for n := 0; n < q.Len(); n++ {
if get(q, n) != x {
if q.At(n) != x {
t.Fatalf("a[%d] != %d after rotate and copy", n, x)
}
x++
@ -261,6 +261,28 @@ func TestRotate(t *testing.T) {
}
}
func TestAt(t *testing.T) {
var q Deque
for i := 0; i < 1000; i++ {
q.PushBack(i)
}
// Front to back.
for j := 0; j < q.Len(); j++ {
if q.At(j).(int) != j {
t.Errorf("index %d doesn't contain %d", j, j)
}
}
// Back to front
for j := 1; j <= q.Len(); j++ {
if q.At(q.Len()-j).(int) != q.Len()-j {
t.Errorf("index %d doesn't contain %d", q.Len()-j, q.Len()-j)
}
}
}
func TestClear(t *testing.T) {
var q Deque
@ -293,9 +315,24 @@ func TestInsert(t *testing.T) {
for _, x := range "ABCDEFG" {
q.PushBack(x)
}
insert(q, 4, 'x') // ABCDxEFG
insert(q, 2, 'y') // AByCDxEFG
insert(q, 0, 'b') // bAByCDxEFG
insert(q, 4, 'x') // ABCDxEFG
if q.At(4) != 'x' {
t.Error("expected x at position 4")
}
insert(q, 2, 'y') // AByCDxEFG
if q.At(2) != 'y' {
t.Error("expected y at position 2")
}
if q.At(5) != 'x' {
t.Error("expected x at position 5")
}
insert(q, 0, 'b') // bAByCDxEFG
if q.Front() != 'b' {
t.Error("expected b inserted at front")
}
insert(q, q.Len(), 'e') // bAByCDxEFGe
for i, x := range "bAByCDxEFGe" {
@ -314,9 +351,16 @@ func TestRemove(t *testing.T) {
if remove(q, 4) != 'E' { // ABCDFG
t.Error("expected E from position 4")
}
if q.At(4) != 'F' {
t.Error("expected F at position 4")
}
if remove(q, 2) != 'C' { // ABDFG
t.Error("expected C at position 2")
}
if q.At(2) != 'D' {
t.Error("expected D at position 4")
}
if q.Back() != 'G' {
t.Error("expected G at back")
}
@ -391,6 +435,22 @@ func TestPopBackOutOfRangePanics(t *testing.T) {
})
}
func TestAtOutOfRangePanics(t *testing.T) {
var q Deque
q.PushBack(1)
q.PushBack(2)
q.PushBack(3)
assertPanics(t, "should panic when negative index", func() {
q.At(-4)
})
assertPanics(t, "should panic when index greater than length", func() {
q.At(4)
})
}
func TestInsertOutOfRangePanics(t *testing.T) {
q := new(Deque)
@ -562,16 +622,3 @@ func remove(q *Deque, i int) interface{} {
q.Rotate(rots)
return elem
}
// get returns the element at index i in the queue without removing the element
// from the queue. This method accepts only non-negative index values. get(0)
// refers to the first element and is the same as Front(). get(Len()-1) refers
// to the last element and is the same as Back(). If the index is invalid, the
// call panics.
func get(q Deque, i int) interface{} {
if i < 0 || i >= q.count {
panic("deque: get() called with index out of range")
}
// bitwise modulus
return q.buf[(q.head+i)&(len(q.buf)-1)]
}