Add Insert and Remove. No negative indexing.
This commit is contained in:
parent
61131f5ce5
commit
e0df3df127
98
deque.go
98
deque.go
|
@ -123,23 +123,99 @@ func (q *Deque) Back() interface{} {
|
|||
return q.buf[(q.tail-1)&(len(q.buf)-1)]
|
||||
}
|
||||
|
||||
// PeekAt returns the element at index i in the queue. This method accepts
|
||||
// both positive and negative index values. PeekAt(0) refers to the first
|
||||
// (earliest added) element and is the same as Front(). PeekAt(-1) refers to
|
||||
// the last (latest added) element and is the same as Back(). If the index
|
||||
// is invalid, the call panics.
|
||||
func (q *Deque) PeekAt(i int) interface{} {
|
||||
// If indexing backwards, convert to positive index.
|
||||
if i < 0 {
|
||||
i += q.count
|
||||
}
|
||||
// Peek returns the element at index i in the queue. This method accepts only
|
||||
// non-negative index values. Peek(0) refers to the first element and is the
|
||||
// same as Front(). q.Peek(Len()-1) refers to the last element and is the same
|
||||
// as Back(). If the index is invalid, the call panics.
|
||||
func (q *Deque) Peek(i int) interface{} {
|
||||
if i < 0 || i >= q.count {
|
||||
panic("deque: PeekAt() called with index out of range")
|
||||
panic("deque: Peek() called with index out of range")
|
||||
}
|
||||
// bitwise modulus
|
||||
return q.buf[(q.head+i)&(len(q.buf)-1)]
|
||||
}
|
||||
|
||||
// Insert is used to insert an element into the queue at a location other than
|
||||
// one of the ends. Insert(0,e) is the same as PushFront(e) and
|
||||
// Insert(Len(),e) is the same as PushBack(e). Accepts only non-negative index
|
||||
// values, and panics if index is out of range.
|
||||
func (q *Deque) Insert(i int, elem interface{}) {
|
||||
if i < 0 || i > q.count {
|
||||
panic("deque: Insert() called with index out of range")
|
||||
}
|
||||
if i == 0 {
|
||||
q.PushFront(elem)
|
||||
return
|
||||
}
|
||||
if i == q.count {
|
||||
q.PushBack(elem)
|
||||
return
|
||||
}
|
||||
if i <= q.count/2 {
|
||||
// If inserting closer to front, rotate front to back i places, put
|
||||
// element at front, then rotate back to front i places.
|
||||
for j := 0; j < i; j++ {
|
||||
q.PushBack(q.PopFront())
|
||||
}
|
||||
q.PushFront(elem)
|
||||
for j := 0; j < i; j++ {
|
||||
q.PushFront(q.PopBack())
|
||||
}
|
||||
} else {
|
||||
// If inserting closer to back, rotate back to font Len() - i places,
|
||||
// put element at back, then rotate front to back same amount.
|
||||
rots := q.count - i
|
||||
for j := 0; j < rots; j++ {
|
||||
q.PushFront(q.PopBack())
|
||||
}
|
||||
q.PushBack(elem)
|
||||
for j := 0; j < rots; j++ {
|
||||
q.PushBack(q.PopFront())
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Remove removes and returns an element from the queue, from a location other
|
||||
// than one of the ends. Remove(0) is the same as PopFront() and
|
||||
// Remove(Len()-1) is the same as PopBack(). Accepts only non-negative index
|
||||
// values, and panics if index is out of range.
|
||||
func (q *Deque) Remove(i int) interface{} {
|
||||
if i < 0 || i >= q.count {
|
||||
panic("deque: Remove() called with index out of range")
|
||||
}
|
||||
if i == 0 {
|
||||
return q.PopFront()
|
||||
}
|
||||
if i == q.count-1 {
|
||||
return q.PopBack()
|
||||
}
|
||||
var elem interface{}
|
||||
if i <= q.count/2 {
|
||||
// If removing closer to front, rotate front to back i places, remove
|
||||
// element at front, then rotate back to front i places.
|
||||
for j := 0; j < i; j++ {
|
||||
q.PushBack(q.PopFront())
|
||||
}
|
||||
elem = q.PopFront()
|
||||
for j := 0; j < i; j++ {
|
||||
q.PushFront(q.PopBack())
|
||||
}
|
||||
} else {
|
||||
// If removing closer to back, rotate back to font Len() - 1 - i
|
||||
// places, remove element at back, then rotate front to back same
|
||||
// amount.
|
||||
rots := (q.count - 1) - i
|
||||
for j := 0; j < rots; j++ {
|
||||
q.PushFront(q.PopBack())
|
||||
}
|
||||
elem = q.PopBack()
|
||||
for j := 0; j < rots; j++ {
|
||||
q.PushBack(q.PopFront())
|
||||
}
|
||||
}
|
||||
return elem
|
||||
}
|
||||
|
||||
// Clear removes all elements from the queue, but retains the current capacity.
|
||||
// The queue will not be resized smaller as long as items are only added.
|
||||
// Only when items are removed is the queue subject to getting resized smaller.
|
||||
|
|
146
deque_test.go
146
deque_test.go
|
@ -52,8 +52,8 @@ func TestGrowShrink(t *testing.T) {
|
|||
}
|
||||
// Check that all values are as expected.
|
||||
for i := 0; i < minCapacity*2; i++ {
|
||||
if q.PeekAt(i) != i {
|
||||
t.Errorf("q.PeekAt(%d) = %d, expected %d", i, q.PeekAt(i), i)
|
||||
if q.Peek(i) != i {
|
||||
t.Errorf("q.Peek(%d) = %d, expected %d", i, q.Peek(i), i)
|
||||
}
|
||||
}
|
||||
bufLen := len(q.buf)
|
||||
|
@ -102,8 +102,8 @@ func TestGrowShrink(t *testing.T) {
|
|||
}
|
||||
}
|
||||
|
||||
func TestDequeSimple(t *testing.T) {
|
||||
q := new(Deque)
|
||||
func TestSimple(t *testing.T) {
|
||||
var q Deque
|
||||
|
||||
for i := 0; i < minCapacity; i++ {
|
||||
q.PushBack(i)
|
||||
|
@ -130,8 +130,8 @@ func TestDequeSimple(t *testing.T) {
|
|||
}
|
||||
}
|
||||
|
||||
func TestDequeWrap(t *testing.T) {
|
||||
q := new(Deque)
|
||||
func TestBufferWrap(t *testing.T) {
|
||||
var q Deque
|
||||
|
||||
for i := 0; i < minCapacity; i++ {
|
||||
q.PushBack(i)
|
||||
|
@ -150,8 +150,8 @@ func TestDequeWrap(t *testing.T) {
|
|||
}
|
||||
}
|
||||
|
||||
func TestDequeWrapReverse(t *testing.T) {
|
||||
q := new(Deque)
|
||||
func TestBufferWrapReverse(t *testing.T) {
|
||||
var q Deque
|
||||
|
||||
for i := 0; i < minCapacity; i++ {
|
||||
q.PushFront(i)
|
||||
|
@ -169,8 +169,8 @@ func TestDequeWrapReverse(t *testing.T) {
|
|||
}
|
||||
}
|
||||
|
||||
func TestDequeLen(t *testing.T) {
|
||||
q := new(Deque)
|
||||
func TestLen(t *testing.T) {
|
||||
var q Deque
|
||||
|
||||
if q.Len() != 0 {
|
||||
t.Error("empty queue length not 0")
|
||||
|
@ -190,34 +190,30 @@ func TestDequeLen(t *testing.T) {
|
|||
}
|
||||
}
|
||||
|
||||
func TestDequePeekAt(t *testing.T) {
|
||||
q := new(Deque)
|
||||
func TestPeek(t *testing.T) {
|
||||
var q Deque
|
||||
|
||||
for i := 0; i < 1000; i++ {
|
||||
q.PushBack(i)
|
||||
for j := 0; j < q.Len(); j++ {
|
||||
if q.PeekAt(j).(int) != j {
|
||||
t.Errorf("index %d doesn't contain %d", j, j)
|
||||
}
|
||||
}
|
||||
|
||||
// Front to back.
|
||||
for j := 0; j < q.Len(); j++ {
|
||||
if q.Peek(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.Peek(q.Len()-j).(int) != q.Len()-j {
|
||||
t.Errorf("index %d doesn't contain %d", q.Len()-j, q.Len()-j)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestDequePeekAtNegative(t *testing.T) {
|
||||
q := new(Deque)
|
||||
|
||||
for i := 0; i < 1000; i++ {
|
||||
q.PushBack(i)
|
||||
for j := 1; j <= q.Len(); j++ {
|
||||
if q.PeekAt(-j).(int) != q.Len()-j {
|
||||
t.Errorf("index %d doesn't contain %d", -j, q.Len()-j)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestDequeBack(t *testing.T) {
|
||||
q := new(Deque)
|
||||
func TestBack(t *testing.T) {
|
||||
var q Deque
|
||||
|
||||
for i := 0; i < minCapacity+5; i++ {
|
||||
q.PushBack(i)
|
||||
|
@ -228,7 +224,7 @@ func TestDequeBack(t *testing.T) {
|
|||
}
|
||||
|
||||
func TestCopy(t *testing.T) {
|
||||
q := new(Deque)
|
||||
var q Deque
|
||||
a := make([]interface{}, minCapacity)
|
||||
if q.Copy(a) != 0 {
|
||||
t.Error("Copied wrong size, expected 0")
|
||||
|
@ -265,7 +261,7 @@ func TestCopy(t *testing.T) {
|
|||
}
|
||||
|
||||
func TestRotate(t *testing.T) {
|
||||
q := new(Deque)
|
||||
var q Deque
|
||||
for i := 0; i < 10; i++ {
|
||||
q.PushBack(i)
|
||||
}
|
||||
|
@ -300,8 +296,8 @@ func TestRotate(t *testing.T) {
|
|||
}
|
||||
}
|
||||
|
||||
func TestDequeClear(t *testing.T) {
|
||||
q := new(Deque)
|
||||
func TestClear(t *testing.T) {
|
||||
var q Deque
|
||||
|
||||
for i := 0; i < 100; i++ {
|
||||
q.PushBack(i)
|
||||
|
@ -327,25 +323,79 @@ func TestDequeClear(t *testing.T) {
|
|||
}
|
||||
}
|
||||
|
||||
func TestPeekAtOutOfRangePanics(t *testing.T) {
|
||||
q := new(Deque)
|
||||
func TestInsert(t *testing.T) {
|
||||
var q Deque
|
||||
q.PushBack("A")
|
||||
q.PushBack("B")
|
||||
q.PushBack("C")
|
||||
q.PushBack("D")
|
||||
q.PushBack("E")
|
||||
q.PushBack("F")
|
||||
q.PushBack("G")
|
||||
|
||||
q.Insert(4, "x")
|
||||
if q.Peek(4) != "x" {
|
||||
t.Error("expected x at position 4")
|
||||
}
|
||||
|
||||
q.Insert(2, "y")
|
||||
if q.Peek(2) != "y" {
|
||||
t.Error("expected y at position 2")
|
||||
}
|
||||
|
||||
if q.Peek(5) != "x" {
|
||||
t.Error("expected x at position 5")
|
||||
}
|
||||
}
|
||||
|
||||
func TestRemove(t *testing.T) {
|
||||
var q Deque
|
||||
q.PushBack("A")
|
||||
q.PushBack("B")
|
||||
q.PushBack("C")
|
||||
q.PushBack("D")
|
||||
q.PushBack("E")
|
||||
q.PushBack("F")
|
||||
q.PushBack("G")
|
||||
|
||||
if q.Remove(4) != "E" {
|
||||
t.Error("expected E from position 4")
|
||||
}
|
||||
if q.Peek(4) != "F" {
|
||||
t.Error("expected F at position 4")
|
||||
}
|
||||
|
||||
if q.Remove(2) != "C" {
|
||||
t.Error("expected C at position 2")
|
||||
}
|
||||
if q.Peek(2) != "D" {
|
||||
t.Error("expected D at position 4")
|
||||
}
|
||||
|
||||
if q.Peek(4) != "G" {
|
||||
t.Error("expected G at position 4")
|
||||
}
|
||||
}
|
||||
|
||||
func TestPeekOutOfRangePanics(t *testing.T) {
|
||||
var q Deque
|
||||
|
||||
q.PushBack(1)
|
||||
q.PushBack(2)
|
||||
q.PushBack(3)
|
||||
|
||||
assertPanics(t, "should panic when negative index", func() {
|
||||
q.PeekAt(-4)
|
||||
q.Peek(-4)
|
||||
})
|
||||
|
||||
assertPanics(t, "should panic when index greater than length", func() {
|
||||
q.PeekAt(4)
|
||||
q.Peek(4)
|
||||
})
|
||||
}
|
||||
|
||||
func TestFrontBackOutOfRangePanics(t *testing.T) {
|
||||
const msg = "should panic when peeking empty queue"
|
||||
q := new(Deque)
|
||||
var q Deque
|
||||
assertPanics(t, msg, func() {
|
||||
q.Front()
|
||||
})
|
||||
|
@ -365,7 +415,7 @@ func TestFrontBackOutOfRangePanics(t *testing.T) {
|
|||
}
|
||||
|
||||
func TestPopFrontOutOfRangePanics(t *testing.T) {
|
||||
q := new(Deque)
|
||||
var q Deque
|
||||
|
||||
assertPanics(t, "should panic when removing empty queue", func() {
|
||||
q.PopFront()
|
||||
|
@ -380,7 +430,7 @@ func TestPopFrontOutOfRangePanics(t *testing.T) {
|
|||
}
|
||||
|
||||
func TestPopBackOutOfRangePanics(t *testing.T) {
|
||||
q := new(Deque)
|
||||
var q Deque
|
||||
|
||||
assertPanics(t, "should panic when removing empty queue", func() {
|
||||
q.PopBack()
|
||||
|
@ -456,7 +506,7 @@ func BenchmarkSerialReverse(b *testing.B) {
|
|||
}
|
||||
|
||||
func BenchmarkRotate(b *testing.B) {
|
||||
q := new(Deque)
|
||||
var q Deque
|
||||
for i := 0; i < size; i++ {
|
||||
q.PushBack(i)
|
||||
}
|
||||
|
@ -470,7 +520,7 @@ func BenchmarkRotate(b *testing.B) {
|
|||
}
|
||||
|
||||
func BenchmarkRotateReverse(b *testing.B) {
|
||||
q := new(Deque)
|
||||
var q Deque
|
||||
for i := 0; i < size; i++ {
|
||||
q.PushBack(i)
|
||||
}
|
||||
|
@ -483,21 +533,21 @@ func BenchmarkRotateReverse(b *testing.B) {
|
|||
}
|
||||
}
|
||||
|
||||
func BenchmarkDequePeekAt(b *testing.B) {
|
||||
q := new(Deque)
|
||||
func BenchmarkDequePeek(b *testing.B) {
|
||||
var q Deque
|
||||
for i := 0; i < size; i++ {
|
||||
q.PushBack(i)
|
||||
}
|
||||
b.ResetTimer()
|
||||
for i := 0; i < b.N; i++ {
|
||||
for j := 0; j < size; j++ {
|
||||
q.PeekAt(j)
|
||||
q.Peek(j)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func BenchmarkDequePushPop(b *testing.B) {
|
||||
q := new(Deque)
|
||||
var q Deque
|
||||
for i := 0; i < b.N; i++ {
|
||||
for n := 0; n < size; n++ {
|
||||
q.PushBack(nil)
|
||||
|
|
Loading…
Reference in a new issue