Files
leetcode/data-structure/ds-deque.go
T
2026-07-20 19:57:25 +08:00

101 lines
2.0 KiB
Go

package ds
// ds-deque.go
// 泛型双端队列,基于环形缓冲。PushFront/PushBack/PopFront/PopBack 全 O(1) 均摊。
// 当容量不足时扩容为 2 倍,自动重新对齐。
// Deque 双端队列,零值可用。
type Deque[T any] struct {
buf []T
head int // 队首索引,逆时针(向后)增长
tail int // 队尾索引 +1
n int // 元素个数
}
// Len 元素个数。
func (d *Deque[T]) Len() int { return d.n }
// Empty 是否为空。
func (d *Deque[T]) Empty() bool { return d.n == 0 }
// PushBack 尾部插入。
func (d *Deque[T]) PushBack(v T) {
d.grow()
d.buf[d.tail] = v
d.tail = (d.tail + 1) % len(d.buf)
d.n++
}
// PushFront 头部插入。
func (d *Deque[T]) PushFront(v T) {
d.grow()
d.head = (d.head - 1 + len(d.buf)) % len(d.buf)
d.buf[d.head] = v
d.n++
}
// PopBack 尾部弹出;空返回零值和 false。
func (d *Deque[T]) PopBack() (T, bool) {
var zero T
if d.n == 0 {
return zero, false
}
d.tail = (d.tail - 1 + len(d.buf)) % len(d.buf)
v := d.buf[d.tail]
d.buf[d.tail] = zero
d.n--
return v, true
}
// PopFront 头部弹出;空返回零值和 false。
func (d *Deque[T]) PopFront() (T, bool) {
var zero T
if d.n == 0 {
return zero, false
}
v := d.buf[d.head]
d.buf[d.head] = zero
d.head = (d.head + 1) % len(d.buf)
d.n--
return v, true
}
// Front 查看头部,不移除。
func (d *Deque[T]) Front() (T, bool) {
var zero T
if d.n == 0 {
return zero, false
}
return d.buf[d.head], true
}
// Back 查看尾部,不移除。
func (d *Deque[T]) Back() (T, bool) {
var zero T
if d.n == 0 {
return zero, false
}
return d.buf[(d.tail-1+len(d.buf))%len(d.buf)], true
}
// grow 容量不足时扩容并重新对齐。
func (d *Deque[T]) grow() {
if d.buf == nil {
d.buf = make([]T, 8)
return
}
if d.n < len(d.buf) {
return
}
oldCap := len(d.buf)
newCap := oldCap * 2
nb := make([]T, newCap)
// 把 head..head+n 的环形数据复制到新缓冲区前端。
for i := 0; i < d.n; i++ {
nb[i] = d.buf[(d.head+i)%oldCap]
}
d.buf = nb
d.head = 0
d.tail = d.n
}