mirror of
https://github.com/hlccd/goSTL.git
synced 2025-01-18 22:09:33 +08:00
273 lines
7.7 KiB
Go
273 lines
7.7 KiB
Go
package deque
|
|
|
|
//@Title deque
|
|
//@Description
|
|
// deque双队列容器包
|
|
// 区别于queue的动态数组实现方式,deque采取将数组和链表相结合的方案
|
|
// 该容器既可以在首部增删元素,也可以在尾部增删元素
|
|
// deque在扩容和缩容时,都是固定增加2^10的空间,同时这一部分空间形成链表节点,并串成链表去保存
|
|
// 可接纳不同类型的元素
|
|
// 通过并发控制锁保证了在高并发过程中的数据一致性
|
|
|
|
import (
|
|
"github.com/hlccd/goSTL/utils/iterator"
|
|
"sync"
|
|
)
|
|
|
|
//deque双向队列结构体
|
|
//包含链表的头尾节点指针
|
|
//当删除节点时通过头尾节点指针进入链表进行删除
|
|
//当一个节点全部被删除后则释放该节点,同时首尾节点做相应调整
|
|
//当添加节点时若未占满节点空间时移动下标并做覆盖即可
|
|
//当添加节点时空间已使用完毕时,根据添加位置新建一个新节点补充上去
|
|
type Deque struct {
|
|
first *node //链表首节点指针
|
|
last *node //链表尾节点指针
|
|
size uint64 //当前存储的元素个数
|
|
mutex sync.Mutex //并发控制锁
|
|
}
|
|
|
|
//deque双向队列容器接口
|
|
//存放了deque容器可使用的函数
|
|
//对应函数介绍见下方
|
|
|
|
type dequer interface {
|
|
Iterator() (i *Iterator.Iterator) //返回包含双向队列中所有元素的迭代器
|
|
Size() (size uint64) //返回该双向队列中元素的使用空间大小
|
|
Clear() //清空该双向队列
|
|
Empty() (b bool) //判断该双向队列是否为空
|
|
PushFront(e interface{}) //将元素e添加到该双向队列的首部
|
|
PushBack(e interface{}) //将元素e添加到该双向队列的尾部
|
|
PopFront() (e interface{}) //将该双向队列首元素弹出
|
|
PopBack() (e interface{}) //将该双向队列首元素弹出
|
|
Front() (e interface{}) //获取该双向队列首部元素
|
|
Back() (e interface{}) //获取该双向队列尾部元素
|
|
}
|
|
|
|
//@title New
|
|
//@description
|
|
// 新建一个deque双向队列容器并返回
|
|
// 初始deque双向队列的链表首尾节点为nil
|
|
// 初始size为0
|
|
//@receiver nil
|
|
//@param nil
|
|
//@return d *Deque 新建的deque指针
|
|
func New() *Deque {
|
|
return &Deque{
|
|
first: nil,
|
|
last: nil,
|
|
size: 0,
|
|
mutex: sync.Mutex{},
|
|
}
|
|
}
|
|
|
|
//@title Iterator
|
|
//@description
|
|
// 以deque双向队列容器做接收者
|
|
// 将deque双向队列容器中所承载的元素放入迭代器中
|
|
// 节点的冗余空间不释放
|
|
//@receiver d *Deque 接收者的deque指针
|
|
//@param nil
|
|
//@return i *iterator.Iterator 新建的Iterator迭代器指针
|
|
func (d *Deque) Iterator() (i *Iterator.Iterator) {
|
|
if d == nil {
|
|
d = New()
|
|
}
|
|
tmp := make([]interface{}, 0, d.size)
|
|
//遍历链表的所有节点,将其中承载的元素全部复制出来
|
|
for m := d.first; m != nil; m = m.nextNode() {
|
|
tmp = append(tmp, m.value()...)
|
|
}
|
|
return Iterator.New(&tmp)
|
|
}
|
|
|
|
//@title Size
|
|
//@description
|
|
// 以deque双向队列容器做接收者
|
|
// 返回该容器当前含有元素的数量
|
|
// 该长度并非实际占用空间数量
|
|
// 若容器为空则返回0
|
|
//@receiver d *Deque 接收者的deque指针
|
|
//@param nil
|
|
//@return size uint64 容器中实际使用元素所占空间大小
|
|
func (d *Deque) Size() (size uint64) {
|
|
if d == nil {
|
|
d = New()
|
|
}
|
|
return d.size
|
|
}
|
|
|
|
//@title Clear
|
|
//@description
|
|
// 以deque双向队列容器做接收者
|
|
// 将该容器中所承载的元素清空
|
|
// 将该容器的首尾指针均置nil,将size重置为0
|
|
//@receiver d *Deque 接收者的deque指针
|
|
//@param nil
|
|
//@return nil
|
|
func (d *Deque) Clear() {
|
|
if d == nil {
|
|
d = New()
|
|
return
|
|
}
|
|
d.mutex.Lock()
|
|
d.first = nil
|
|
d.last = nil
|
|
d.size = 0
|
|
d.mutex.Unlock()
|
|
}
|
|
|
|
//@title Empty
|
|
//@description
|
|
// 以deque双向队列容器做接收者
|
|
// 判断该deque双向队列容器是否含有元素
|
|
// 如果含有元素则不为空,返回false
|
|
// 如果不含有元素则说明为空,返回true
|
|
// 如果容器不存在,返回true
|
|
// 该判断过程通过size进行判断,为0则为true,否则为false
|
|
//@receiver d *Deque 接收者的deque指针
|
|
//@param nil
|
|
//@return b bool 该容器是空的吗?
|
|
func (d *Deque) Empty() (b bool) {
|
|
if d == nil {
|
|
d = New()
|
|
}
|
|
return d.Size() == 0
|
|
}
|
|
|
|
//@title PushFront
|
|
//@description
|
|
// 以deque双向队列向量容器做接收者
|
|
// 在容器首部插入元素
|
|
// 通过链表首节点进行添加
|
|
//@receiver d *Deque 接收者的deque指针
|
|
//@param e interface{} 待插入元素
|
|
//@return nil
|
|
func (d *Deque) PushFront(e interface{}) {
|
|
if d == nil {
|
|
d = New()
|
|
}
|
|
d.mutex.Lock()
|
|
d.size++
|
|
//通过首节点进行添加
|
|
if d.first == nil {
|
|
d.first = createFirst()
|
|
d.last = d.first
|
|
}
|
|
d.first = d.first.pushFront(e)
|
|
d.mutex.Unlock()
|
|
}
|
|
|
|
//@title PushBack
|
|
//@description
|
|
// 以deque双向队列向量容器做接收者
|
|
// 在容器尾部插入元素
|
|
// 通过链表尾节点进行添加
|
|
//@receiver d *Deque 接收者的deque指针
|
|
//@param e interface{} 待插入元素
|
|
//@return nil
|
|
func (d *Deque) PushBack(e interface{}) {
|
|
if d == nil {
|
|
d = New()
|
|
}
|
|
d.mutex.Lock()
|
|
d.size++
|
|
//通过尾节点进行添加
|
|
if d.last == nil {
|
|
d.last = createLast()
|
|
d.first = d.last
|
|
}
|
|
d.last = d.last.pushBack(e)
|
|
d.mutex.Unlock()
|
|
}
|
|
|
|
//@title PopFront
|
|
//@description
|
|
// 以deque双向队列容器做接收者
|
|
// 利用首节点进行弹出元素,可能存在首节点全部释放要进行首节点后移的情况
|
|
// 当元素全部删除后,释放全部空间,将首尾节点都设为nil
|
|
//@receiver d *Deque 接收者的deque指针
|
|
//@param nil
|
|
//@return e interface{} 首元素
|
|
func (d *Deque) PopFront() (e interface{}) {
|
|
if d == nil {
|
|
d = New()
|
|
}
|
|
if d.size == 0 {
|
|
return nil
|
|
}
|
|
d.mutex.Lock()
|
|
//利用首节点删除首元素
|
|
//返回新的首节点
|
|
e = d.first.front()
|
|
d.first = d.first.popFront()
|
|
d.size--
|
|
if d.size == 0 {
|
|
//全部删除完成,释放空间,并将首尾节点设为nil
|
|
d.first = nil
|
|
d.last = nil
|
|
}
|
|
d.mutex.Unlock()
|
|
return e
|
|
}
|
|
|
|
//@title PopBack
|
|
//@description
|
|
// 以deque双向队列容器做接收者
|
|
// 利用尾节点进行弹出元素,可能存在尾节点全部释放要进行尾节点前移的情况
|
|
// 当元素全部删除后,释放全部空间,将首尾节点都设为nil
|
|
//@receiver d *Deque 接收者的deque指针
|
|
//@param nil
|
|
//@return e interface{} 尾元素
|
|
func (d *Deque) PopBack() (e interface{}) {
|
|
if d == nil {
|
|
d = New()
|
|
}
|
|
if d.size == 0 {
|
|
return nil
|
|
}
|
|
d.mutex.Lock()
|
|
//利用尾节点删除首元素
|
|
//返回新的尾节点
|
|
d.last = d.last.popBack()
|
|
e = d.last.back()
|
|
d.size--
|
|
if d.size == 0 {
|
|
//全部删除完成,释放空间,并将首尾节点设为nil
|
|
d.first = nil
|
|
d.last = nil
|
|
}
|
|
d.mutex.Unlock()
|
|
return e
|
|
}
|
|
|
|
//@title Front
|
|
//@description
|
|
// 以deque双向队列容器做接收者
|
|
// 返回该容器的第一个元素,利用首节点进行寻找
|
|
// 若该容器当前为空,则返回nil
|
|
//@receiver d *Deque 接收者的deque指针
|
|
//@param nil
|
|
//@return e interface{} 容器的第一个元素
|
|
func (d *Deque) Front() (e interface{}) {
|
|
if d == nil {
|
|
d = New()
|
|
}
|
|
return d.first.front()
|
|
}
|
|
|
|
//@title Back
|
|
//@description
|
|
// 以deque双向队列容器做接收者
|
|
// 返回该容器的最后一个元素,利用尾节点进行寻找
|
|
// 若该容器当前为空,则返回nil
|
|
//@receiver d *Deque 接收者的deque指针
|
|
//@param nil
|
|
//@return e interface{} 容器的最后一个元素
|
|
func (d *Deque) Back() (e interface{}) {
|
|
if d == nil {
|
|
d = New()
|
|
}
|
|
return d.last.back()
|
|
}
|