将所有文件的目录结构进行调整,以保证使用者下载即可用

This commit is contained in:
hlccd
2021-12-29 00:32:14 +08:00
committed by GitHub
parent d105904a78
commit e1b6fae026
38 changed files with 8943 additions and 0 deletions

View File

@@ -0,0 +1,272 @@
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()
}

View File

@@ -0,0 +1,36 @@
package deque
import (
"reflect"
"sync"
"testing"
)
func TestDeque_Front(t *testing.T) {
type fields struct {
first *node
last *node
size uint64
mutex sync.Mutex
}
tests := []struct {
name string
fields fields
wantE interface{}
}{
// TODO: Add test cases.
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
d := &Deque{
first: tt.fields.first,
last: tt.fields.last,
size: tt.fields.size,
mutex: tt.fields.mutex,
}
if gotE := d.Front(); !reflect.DeepEqual(gotE, tt.wantE) {
t.Errorf("Front() = %v, want %v", gotE, tt.wantE)
}
})
}
}

View File

@@ -0,0 +1,263 @@
package deque
//@Title deque
//@Description
// deque双队列容器包
// 该部分包含了deque双向队列中链表节点
// 链表的增删都通过节点的增删完成
// 节点空间全部使用或全部废弃后将进行节点增删
// 增删之后会返回对应的首尾节点以辅助deque容器仍持有首尾节点
// 为保证效率问题,设定了一定的冗余量,即每个节点设定2^10的空间以存放元素
//deque双向队列中链表的node节点结构体
//包含一个2^10空间的固定数组用以承载元素
//使用begin和end两个下标用以表示新增的元素的下标,由于begin可能出现-1所以不选用uint16
//pre和next是该节点的前后两个节点
//用以保证链表整体是相连的
type node struct {
data [1024]interface{} //用于承载元素的股东数组
begin int16 //该结点在前方添加结点的下标
end int16 //该结点在后方添加结点的下标
pre *node //该结点的前一个结点
next *node //该节点的后一个结点
}
//deque双向队列容器接口
//存放了node结点容器可使用的函数
//对应函数介绍见下方
type noder interface {
nextNode() (m *node) //返回下一个结点
preNode() (m *node) //返回上一个结点
value() (es []interface{}) //返回该结点所承载的所有元素
pushFront(e interface{}) (first *node) //在该结点头部添加一个元素,并返回新首结点
pushBack(e interface{}) (last *node) //在该结点尾部添加一个元素,并返回新尾结点
popFront() (first *node) //弹出首元素并返回首结点
popBack() (last *node) //弹出尾元素并返回尾结点
front() (e interface{}) //返回首元素
back() (e interface{}) //返回尾元素
}
//@title createFirst
//@description
// 新建一个冗余在前方的首结点并返回其指针
// 初始首结点的begin为1023,end为1024
// 该结点的前后结点均置为nil
//@receiver nil
//@param nil
//@return n *node 新建的node指针
func createFirst() (n *node) {
return &node{
data: [1024]interface{}{},
begin: 1023,
end: 1024,
pre: nil,
next: nil,
}
}
//@title createLast
//@description
// 新建一个冗余在后方的尾结点并返回其指针
// 初始首结点的begin为-1,end为0
// 该结点的前后结点均置为nil
//@receiver nil
//@param nil
//@return n *node 新建的node指针
func createLast() (n *node) {
return &node{
data: [1024]interface{}{},
begin: -1,
end: 0,
pre: nil,
next: nil,
}
}
//@title nextNode
//@description
// 以node结点做接收者
// 返回该结点的后一个结点
// 如果n为nil则返回nil
//@receiver n *node 接收者的node指针
//@param nil
//@return m *node n结点的下一个结点m的指针
func (n *node) nextNode() (m *node) {
if n == nil {
return nil
}
return n.next
}
//@title preNode
//@description
// 以node结点做接收者
// 返回该结点的前一个结点
// 如果n为nil则返回nil
//@receiver n *node 接收者的node指针
//@param nil
//@return m *node n结点的上一个结点m的指针
func (n *node) preNode() (m *node) {
if n == nil {
return nil
}
return n.pre
}
//@title value
//@description
// 以node结点做接收者
// 返回该结点所承载的所有元素
// 根据其begin和end来获取其元素
// 当该结点为nil时返回[]而非nil
//@receiver n *node 接收者的node指针
//@param nil
//@return es []interface{} 该结点所承载的所有元素
func (n *node) value() (es []interface{}) {
es = make([]interface{}, 0, 0)
if n == nil {
return es
}
if n.begin > n.end {
return es
}
es = n.data[n.begin+1 : n.end]
return es
}
//@title pushFront
//@description
// 以node结点做接收者
// 向该节点前方添加元素e
// 当该结点空间已经使用完毕后,新建一个结点并将新结点设为首结点
// 将插入元素放入新结点并返回新结点作为新的首结点
// 否则插入当前结点并返回当前结点,首结点不变
//@receiver n *node 接收者的node指针
//@param e interface{} 待插入元素
//@return first *node 首节点指针
func (n *node) pushFront(e interface{}) (first *node) {
if n == nil {
return n
}
if n.begin >= 0 {
//该结点仍有空间可用于承载元素
n.data[n.begin] = e
n.begin--
return n
}
//该结点无空间承载,创建新的首结点用于存放
m := createFirst()
m.data[m.begin] = e
m.next = n
n.pre = m
m.begin--
return m
}
//@title pushBack
//@description
// 以node结点做接收者
// 向该节点后方添加元素e
// 当该结点空间已经使用完毕后,新建一个结点并将新结点设为尾结点
// 将插入元素放入新结点并返回新结点作为新的尾结点
// 否则插入当前结点并返回当前结点,尾结点不变
//@receiver n *node 接收者的node指针
//@param e interface{} 待插入元素
//@return last *node 尾节点指针
func (n *node) pushBack(e interface{}) (last *node) {
if n == nil {
return n
}
if n.end < int16(len(n.data)) {
//该结点仍有空间可用于承载元素
n.data[n.end] = e
n.end++
return n
}
//该结点无空间承载,创建新的尾结点用于存放
m := createLast()
m.data[m.end] = e
m.pre = n
n.next = m
m.end++
return m
}
//@title popFront
//@description
// 以node结点做接收者
// 利用首节点进行弹出元素,可能存在首节点全部释放要进行首节点后移的情况
// 当发生首结点后移后将会返回新首结点,否则返回当前结点
//@receiver n *node 接收者的node指针
//@param nil
//@return first *node 首节点指针
func (n *node) popFront() (first *node) {
if n == nil {
return nil
}
if n.begin < int16(len(n.data))-2 {
//该结点仍有承载元素
n.begin++
n.data[n.begin] = nil
return n
}
if n.next != nil {
//清除该结点下一节点的前结点指针
n.next.pre = nil
}
return n.next
}
//@title popBack
//@description
// 以node结点做接收者
// 利用尾节点进行弹出元素,可能存在尾节点全部释放要进行尾节点前移的情况
// 当发生尾结点前移后将会返回新尾结点,否则返回当前结点
//@receiver n *node 接收者的node指针
//@param nil
//@return last *node 尾节点指针
func (n *node) popBack() (last *node) {
if n == nil {
return nil
}
if n.end > 1 {
//该结点仍有承载元素
n.end--
n.data[n.end] = nil
return n
}
if n.pre != nil {
//清除该结点上一节点的后结点指针
n.pre.next = nil
}
return n.pre
}
//@title front
//@description
// 以node结点做接收者
// 返回该结点的第一个元素,利用首节点和begin进行查找
// 若该结点为nil,则返回nil
//@receiver n *node 接收者的node指针
//@param nil
//@return e interface{} 该结点承载的的第一个元素
func (n *node) front() (e interface{}) {
if n == nil {
return nil
}
return n.data[n.begin+1]
}
//@title back
//@description
// 以node结点做接收者
// 返回该结点的最后一个元素,利用尾节点和end进行查找
// 若该结点为nil,则返回nil
//@receiver n *node 接收者的node指针
//@param nil
//@return e interface{} 该结点承载的的最后一个元素
func (n *node) back() (e interface{}) {
if n == nil {
return nil
}
return n.data[n.end-1]
}