274 lines
6.8 KiB
Go
274 lines
6.8 KiB
Go
package deque
|
|
|
|
// minCapacity is the smallest capacity that deque may have.
|
|
// Must be power of 2 for bitwise modulus: x % n == x & (n - 1).
|
|
const minCapacity = 16
|
|
|
|
// Deque represents a single instance of the deque data structure.
|
|
type Deque struct {
|
|
buf []int
|
|
head int
|
|
tail int
|
|
count int
|
|
minCap int
|
|
}
|
|
|
|
// New creates a new Deque, optionally setting the current and minimum capacity
|
|
// when non-zero values are given for these.
|
|
//
|
|
// To create a Deque with capacity to store 2048 items without resizing, and
|
|
// that will not resize below space for 32 items when removing itmes:
|
|
// d := deque.New(2048, 32)
|
|
//
|
|
// To create a Deque that has not yet allocated memory, but after it does will
|
|
// never resize to have space for less than 64 items:
|
|
// d := deque.New(0, 64)
|
|
//
|
|
// Note that any values supplied here are rounded up to the nearest power of 2.
|
|
func New(size ...int) *Deque {
|
|
var capacity, minimum int
|
|
if len(size) >= 1 {
|
|
capacity = size[0]
|
|
if len(size) >= 2 {
|
|
minimum = size[1]
|
|
}
|
|
}
|
|
|
|
minCap := minCapacity
|
|
for minCap < minimum {
|
|
minCap <<= 1
|
|
}
|
|
|
|
var buf []int
|
|
if capacity != 0 {
|
|
bufSize := minCap
|
|
for bufSize < capacity {
|
|
bufSize <<= 1
|
|
}
|
|
buf = make([]int, bufSize)
|
|
}
|
|
|
|
return &Deque{
|
|
buf: buf,
|
|
minCap: minCap,
|
|
}
|
|
}
|
|
|
|
// Cap returns the current capacity of the Deque.
|
|
func (q *Deque) Cap() int {
|
|
return len(q.buf)
|
|
}
|
|
|
|
// Len returns the number of elements currently stored in the queue.
|
|
func (q *Deque) Len() int {
|
|
return q.count
|
|
}
|
|
|
|
// PushBack appends an element to the back of the queue. Implements FIFO when
|
|
// elements are removed with PopFront(), and LIFO when elements are removed
|
|
// with PopBack().
|
|
func (q *Deque) PushBack(elem int) {
|
|
q.growIfFull()
|
|
|
|
q.buf[q.tail] = elem
|
|
// Calculate new tail position.
|
|
q.tail = q.next(q.tail)
|
|
q.count++
|
|
}
|
|
|
|
// PushFront prepends an element to the front of the queue.
|
|
func (q *Deque) PushFront(elem int) {
|
|
q.growIfFull()
|
|
|
|
// Calculate new head position.
|
|
q.head = q.prev(q.head)
|
|
q.buf[q.head] = elem
|
|
q.count++
|
|
}
|
|
|
|
// PopFront removes and returns the element from the front of the queue.
|
|
// Implements FIFO when used with PushBack(). If the queue is empty, the call
|
|
// panics.
|
|
func (q *Deque) PopFront() int {
|
|
if q.count <= 0 {
|
|
panic("deque: PopFront() called on empty queue")
|
|
}
|
|
ret := q.buf[q.head]
|
|
// Calculate new head position.
|
|
q.head = q.next(q.head)
|
|
q.count--
|
|
|
|
q.shrinkIfExcess()
|
|
return ret
|
|
}
|
|
|
|
// PopBack removes and returns the element from the back of the queue.
|
|
// Implements LIFO when used with PushBack(). If the queue is empty, the call
|
|
// panics.
|
|
func (q *Deque) PopBack() int {
|
|
if q.count <= 0 {
|
|
panic("deque: PopBack() called on empty queue")
|
|
}
|
|
|
|
// Calculate new tail position
|
|
q.tail = q.prev(q.tail)
|
|
|
|
// Remove value at tail.
|
|
ret := q.buf[q.tail]
|
|
q.count--
|
|
|
|
q.shrinkIfExcess()
|
|
return ret
|
|
}
|
|
|
|
// Front returns the element at the front of the queue. This is the element
|
|
// that would be returned by PopFront(). This call panics if the queue is
|
|
// empty.
|
|
func (q *Deque) Front() int {
|
|
if q.count <= 0 {
|
|
panic("deque: Front() called when empty")
|
|
}
|
|
return q.buf[q.head]
|
|
}
|
|
|
|
// Back returns the element at the back of the queue. This is the element
|
|
// that would be returned by PopBack(). This call panics if the queue is
|
|
// empty.
|
|
func (q *Deque) Back() int {
|
|
if q.count <= 0 {
|
|
panic("deque: Back() called when empty")
|
|
}
|
|
return q.buf[q.prev(q.tail)]
|
|
}
|
|
|
|
// 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
|
|
// only added. Only when items are removed is the queue subject to getting
|
|
// resized smaller.
|
|
func (q *Deque) Clear() {
|
|
// bitwise modulus
|
|
modBits := len(q.buf) - 1
|
|
for h := q.head; h != q.tail; h = (h + 1) & modBits {
|
|
q.buf[h] = 0
|
|
}
|
|
q.head = 0
|
|
q.tail = 0
|
|
q.count = 0
|
|
}
|
|
|
|
// Reset sets properties to empty, but does not rewrite the buffer
|
|
func (q *Deque) Reset() {
|
|
q.head = 0
|
|
q.tail = 0
|
|
q.count = 0
|
|
}
|
|
|
|
// Rotate rotates the deque n steps front-to-back. If n is negative, rotates
|
|
// back-to-front. Having Deque provide Rotate() avoids resizing that could
|
|
// happen if implementing rotation using only Pop and Push methods.
|
|
func (q *Deque) Rotate(n int) {
|
|
if q.count <= 1 {
|
|
return
|
|
}
|
|
// Rotating a multiple of q.count is same as no rotation.
|
|
n %= q.count
|
|
if n == 0 {
|
|
return
|
|
}
|
|
|
|
modBits := len(q.buf) - 1
|
|
// If no empty space in buffer, only move head and tail indexes.
|
|
if q.head == q.tail {
|
|
// Calculate new head and tail using bitwise modulus.
|
|
q.head = (q.head + n) & modBits
|
|
q.tail = (q.tail + n) & modBits
|
|
return
|
|
}
|
|
|
|
if n < 0 {
|
|
// Rotate back to front.
|
|
for ; n < 0; n++ {
|
|
// Calculate new head and tail using bitwise modulus.
|
|
q.head = (q.head - 1) & modBits
|
|
q.tail = (q.tail - 1) & modBits
|
|
// Put tail value at head and remove value at tail.
|
|
q.buf[q.head] = q.buf[q.tail]
|
|
}
|
|
return
|
|
}
|
|
|
|
// Rotate front to back.
|
|
for ; n > 0; n-- {
|
|
// Put head value at tail and remove value at head.
|
|
q.buf[q.tail] = q.buf[q.head]
|
|
// Calculate new head and tail using bitwise modulus.
|
|
q.head = (q.head + 1) & modBits
|
|
q.tail = (q.tail + 1) & modBits
|
|
}
|
|
}
|
|
|
|
// SetMinCapacity sets a minimum capacity of 2^minCapacityExp. If the value of
|
|
// the minimum capacity is less than or equal to the minimum allowed, then
|
|
// capacity is set to the minimum allowed. This may be called at anytime to
|
|
// set a new minimum capacity.
|
|
//
|
|
// Setting a larger minimum capacity may be used to prevent resizing when the
|
|
// number of stored items changes frequently across a wide range.
|
|
func (q *Deque) SetMinCapacity(minCapacityExp uint) {
|
|
if 1<<minCapacityExp > minCapacity {
|
|
q.minCap = 1 << minCapacityExp
|
|
} else {
|
|
q.minCap = minCapacity
|
|
}
|
|
}
|
|
|
|
// prev returns the previous buffer position wrapping around buffer.
|
|
func (q *Deque) prev(i int) int {
|
|
return (i - 1) & (len(q.buf) - 1) // bitwise modulus
|
|
}
|
|
|
|
// next returns the next buffer position wrapping around buffer.
|
|
func (q *Deque) next(i int) int {
|
|
return (i + 1) & (len(q.buf) - 1) // bitwise modulus
|
|
}
|
|
|
|
// growIfFull resizes up if the buffer is full.
|
|
func (q *Deque) growIfFull() {
|
|
if q.count != len(q.buf) {
|
|
return
|
|
}
|
|
if len(q.buf) == 0 {
|
|
if q.minCap == 0 {
|
|
q.minCap = minCapacity
|
|
}
|
|
q.buf = make([]int, q.minCap)
|
|
return
|
|
}
|
|
q.resize()
|
|
}
|
|
|
|
// shrinkIfExcess resize down if the buffer 1/4 full.
|
|
func (q *Deque) shrinkIfExcess() {
|
|
if len(q.buf) > q.minCap && (q.count<<2) == len(q.buf) {
|
|
q.resize()
|
|
}
|
|
}
|
|
|
|
// resize resizes the deque to fit exactly twice its current contents. This is
|
|
// used to grow the queue when it is full, and also to shrink it when it is
|
|
// only a quarter full.
|
|
func (q *Deque) resize() {
|
|
newBuf := make([]int, q.count<<1)
|
|
if q.tail > q.head {
|
|
copy(newBuf, q.buf[q.head:q.tail])
|
|
} else {
|
|
n := copy(newBuf, q.buf[q.head:])
|
|
copy(newBuf[n:], q.buf[:q.tail])
|
|
}
|
|
|
|
q.head = 0
|
|
q.tail = q.count
|
|
q.buf = newBuf
|
|
}
|