使用动态数组实现了vector,利用并发控制锁保证了在高并发过程中的线程安全

This commit is contained in:
hlccd 2021-10-20 13:05:30 +08:00 committed by GitHub
parent dff0e50974
commit fb520f4e85
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23

View File

@ -18,10 +18,12 @@ import (
//vector向量结构体
//包含泛型切片和该切片的尾指针
//当删除节点时仅仅需要前移尾指针一位即可
//当剩余长度小于实际占用空间长度的一半时会重新规划以释放掉多余占用的空间
//当添加节点时若未占满全部已分配空间则尾指针后移一位同时进行覆盖存放
//当添加节点时尾指针大于已分配空间长度,则新增空间
//当删除节点时仅仅需要长度-1即可
//当剩余长度较小时会采取缩容策略释放空间
//当添加节点时若未占满全部已分配空间则长度+1同时进行覆盖存放
//当添加节点时尾指针大于已分配空间长度,则按照扩容策略进行扩容
//并发控制锁用以保证在高并发过程中不会出现错误
//使用比较器重载了Sort
type vector struct {
data []interface{} //动态数组
@ -35,17 +37,17 @@ type vector struct {
//对应函数介绍见下方
type vectorer interface {
Iterator() *Iterator.Iterator //返回一个包含vector所有元素的迭代器
Iterator() (i *Iterator.Iterator) //返回一个包含vector所有元素的迭代器
Sort(Cmp ...comparator.Comparator) //利用比较器对其进行排序
Size() (num int) //返回vector的长度
Size() (num uint64) //返回vector的长度
Clear() //清空vector
Empty() (b bool) //返回vector是否为空,为空则返回true反之返回false
PushBack(e interface{}) //向vector末尾插入一个元素
PopBack() //弹出vector末尾元素
Insert(idx int, e interface{}) //向vector第idx的位置插入元素e,同时idx后的其他元素向后退一位
Erase(idx int) //删除vector的第idx个元素
Insert(idx uint64, e interface{}) //向vector第idx的位置插入元素e,同时idx后的其他元素向后退一位
Erase(idx uint64) //删除vector的第idx个元素
Reverse() //逆转vector中的数据顺序
At(idx int) (e interface{}) //返回vector的第idx的元素
At(idx uint64) (e interface{}) //返回vector的第idx的元素
Front() (e interface{}) //返回vector的第一个元素
Back() (e interface{}) //返回vector的最后一个元素
}
@ -54,14 +56,15 @@ type vectorer interface {
//@description
// 新建一个vector向量容器并返回
// 初始vector的切片数组为空
// 初始vector的尾指针置0
// 初始vector的长度为0,容量为1
//@receiver nil
//@param nil
//@return v *vector 新建的vector指针
func New() (v *vector) {
return &vector{
data: make([]interface{}, 1, 1),
end: 0,
len: 0,
cap: 1,
mutex: sync.Mutex{},
}
}
@ -69,22 +72,28 @@ func New() (v *vector) {
//@title Iterator
//@description
// 以vector向量容器做接收者
// 将vector向量容器中不使用空间释放掉
// 释放未使用的空间,并将已使用的部分用于创建迭代器
// 返回一个包含容器中所有使用元素的迭代器
//@receiver v *vector 接受者vector的指针
//@param nil
//@return i *iterator.Iterator 新建的Iterator迭代器指针
func (v *vector) Iterator() (i *Iterator.Iterator) {
if v == nil {
v.data = make([]interface{}, 1, 1)
v.end = 0
v = New()
}
v.mutex.Lock()
if v.end > 0 {
v.data = v.data[:v.end]
} else {
if v.data == nil {
//data不存在,新建一个
v.data = make([]interface{}, 1, 1)
v.len = 0
v.cap = 1
} else if v.len < v.cap {
//释放未使用的空间
tmp := make([]interface{}, v.len, v.len)
copy(tmp, v.data)
v.data = tmp
}
//创建迭代器
i = Iterator.New(&v.data)
v.mutex.Unlock()
return i
@ -100,14 +109,22 @@ func (v *vector) Iterator() (i *Iterator.Iterator) {
//@return i *iterator.Iterator 新建的Iterator迭代器指针
func (v *vector) Sort(Cmp ...comparator.Comparator) {
if v == nil {
v.data = make([]interface{}, 1, 1)
v = New()
}
v.mutex.Lock()
if v.end > 0 {
v.data = v.data[:v.end]
} else {
v.data = make([]interface{}, 0, 0)
if v.data == nil {
//data不存在,新建一个
v.data = make([]interface{}, 1, 1)
v.len = 0
v.cap = 1
} else if v.len < v.cap {
//释放未使用空间
tmp := make([]interface{}, v.len, v.len)
copy(tmp, v.data)
v.data = tmp
v.cap = v.len
}
//调用比较器的Sort进行排序
if len(Cmp) == 0 {
comparator.Sort(&v.data)
} else {
@ -120,35 +137,33 @@ func (v *vector) Sort(Cmp ...comparator.Comparator) {
//@description
// 以vector向量容器做接收者
// 返回该容器当前含有元素的数量
// 该长度并非实际占用空间数量
// 如果容器为nil返回-1
//@auth hlccd 2021-07-4
// 该长度并非实际占用空间数量,而是实际使用空间
//@receiver v *vector 接受者vector的指针
//@param nil
//@return num int 容器中实际使用元素所占空间大小
func (v *vector) Size() (num int) {
func (v *vector) Size() (num uint64) {
if v == nil {
return -1
v = New()
}
return v.end
return v.len
}
//@title Clear
//@description
// 以vector向量容器做接收者
// 将该容器中所承载的元素清空
// 将该容器的尾指针置0
//@auth hlccd 2021-07-4
// 将该容器中的动态数组重置,所承载的元素清空
//@receiver v *vector 接受者vector的指针
//@param nil
//@return nil
func (v *vector) Clear() {
if v == nil {
return
v = New()
}
v.mutex.Lock()
v.data = v.data[0:0]
v.end = 0
//清空data
v.data = make([]interface{}, 1, 1)
v.len = 0
v.cap = 1
v.mutex.Unlock()
}
@ -158,17 +173,15 @@ func (v *vector) Clear() {
// 判断该vector向量容器是否含有元素
// 如果含有元素则不为空,返回false
// 如果不含有元素则说明为空,返回true
// 如果容器不存在,返回true
// 该判断过程通过尾指针数值进行判断
// 当尾指针数值为0时说明不含有元素
// 当尾指针数值大于0时说明含有元素
//@auth hlccd 2021-07-4
// 该判断过程通过长度进行判断
// 当长度为0时说明不含有元素
// 当长度大于0时说明含有元素
//@receiver v *vector 接受者vector的指针
//@param nil
//@return b bool 该容器是空的吗?
func (v *vector) Empty() (b bool) {
if v == nil {
return true
v = New()
}
return v.Size() <= 0
}
@ -177,47 +190,74 @@ func (v *vector) Empty() (b bool) {
//@description
// 以vector向量容器做接收者
// 在容器尾部插入元素
// 若尾指针小于切片实际使用长度,则对当前指针位置进行覆盖,同时尾指针后移一位
// 若尾指针等于切片实际使用长度,则新增切片长度同时使尾指针后移一位
//@auth hlccd 2021-07-4
// 若长度小于容量时,则对以长度为下标的位置进行覆盖,同时len++
// 若长度等于容量时,需要进行扩容
// 对于扩容而言,当容量小于2^16时,直接将容量翻倍,否则将容量增加2^16
//@receiver v *vector 接受者vector的指针
//@param e interface{} 待插入元素
//@return nil
func (v *vector) PushBack(e interface{}) {
if v == nil {
return
v = New()
}
v.mutex.Lock()
if v.end < len(v.data) {
v.data[v.end] = e
if v.len < v.cap {
//还有冗余,直接添加
v.data[v.len] = e
} else {
v.data = append(v.data, e)
//冗余不足,需要扩容
if v.cap < 2^16 {
//容量翻倍
if v.cap == 0 {
v.cap = 1
}
v.end++
v.cap *= 2
} else {
//容量增加2^16
v.cap += 2 ^ 16
}
//复制扩容前的元素
tmp := make([]interface{}, v.cap, v.cap)
copy(tmp, v.data)
v.data = tmp
v.data[v.len] = e
}
v.len++
v.mutex.Unlock()
}
//@title PopBack
//@description
// 以vector向量容器做接收者
// 弹出容器最后一个元素,同时尾指针前移一位
// 当尾指针小于容器切片实际使用空间的一半时,重新分配空间释放未使用部分
// 弹出容器最后一个元素,同时长度--即可
// 若容器为空,则不进行弹出
//@auth hlccd 2021-07-4
// 当弹出元素后,可能进行缩容
// 当容量和实际使用差值超过2^16时,容量直接减去2^16
// 否则,当实际使用长度是容量的一半时,进行折半缩容
//@receiver v *vector 接受者vector的指针
//@param nil
//@return nil
func (v *vector) PopBack() {
if v == nil {
return
v = New()
}
if v.Empty() {
return
}
v.mutex.Lock()
v.end--
if v.end*2 <= len(v.data) {
v.data = v.data[0:v.end]
v.len--
if v.cap-v.len >= 2^16 {
//容量和实际使用差值超过2^16时,容量直接减去2^16
v.cap -= 2 ^ 16
tmp := make([]interface{}, v.cap, v.cap)
copy(tmp, v.data)
v.data = tmp
} else if v.len*2 < v.cap {
//实际使用长度是容量的一半时,进行折半缩容
v.cap /= 2
tmp := make([]interface{}, v.cap, v.cap)
copy(tmp, v.data)
v.data = tmp
}
v.mutex.Unlock()
}
@ -229,28 +269,41 @@ func (v *vector) PopBack() {
// 当idx不大于0时,则在容器切片的头部插入元素
// 当idx不小于切片使用长度时,在容器末尾插入元素
// 否则在切片中间第idx位插入元素,同时后移第idx位以后的元素
// idx从0计算
// 尾指针同步后移一位
//@auth hlccd 2021-07-4
// 根据冗余量选择是否扩容,扩容策略同上
// 插入后len++
//@receiver v *vector 接受者vector的指针
//@param idx int 待插入节点的位置
//@param idx uint64 待插入节点的位置(下标从0开始)
//@param e interface{} 待插入元素
//@return nil
func (v *vector) Insert(idx int, e interface{}) {
func (v *vector) Insert(idx uint64, e interface{}) {
if v == nil {
return
v = New()
}
v.mutex.Lock()
if idx <= 0 {
v.data = append(append([]interface{}{}, e), v.data[:v.end]...)
v.end++
} else if idx >= v.Size() {
v.PushBack(e)
} else {
es := append([]interface{}{}, v.data[idx:v.end]...)
v.data = append(append(v.data[:idx], e), es...)
v.end++
if v.len >= v.cap {
//冗余不足,进行扩容
if v.cap < 2^16 {
//容量翻倍
if v.cap == 0 {
v.cap = 1
}
v.cap *= 2
} else {
//容量增加2^16
v.cap += 2 ^ 16
}
//复制扩容前的元素
tmp := make([]interface{}, v.cap, v.cap)
copy(tmp, v.data)
v.data = tmp
}
//从后往前复制,即将idx后的全部后移一位即可
var p uint64
for p = v.len; p > 0 && p > uint64(idx); p-- {
v.data[p] = v.data[p-1]
}
v.data[p] = e
v.len++
v.mutex.Unlock()
}
@ -258,32 +311,39 @@ func (v *vector) Insert(idx int, e interface{}) {
//@description
// 以vector向量容器做接收者
// 向容器切片中删除一个元素
// 当idx不大于0时,则在容器切片的头部删除
// 当idx不小于切片使用长度时,在容器末尾删除
// 当idx不大于0时,则删除头部
// 当idx不小于切片使用长度时,则删除尾部
// 否则在切片中间第idx位删除元素,同时前移第idx位以后的元素
// idx从0计算
// 尾指针同步后移以为
//@auth hlccd 2021-07-4
// 长度同步--
// 进行缩容判断,缩容策略同上
//@receiver v *vector 接受者vector的指针
//@param idx int 待删除节点的位置
//@param idx uint64 待删除节点的位置(下标从0开始)
//@return nil
func (v *vector) Erase(idx int) {
func (v *vector) Erase(idx uint64) {
if v == nil {
return
v = New()
}
if v.Empty() {
return
}
v.mutex.Lock()
idx++
if idx <= 1 {
idx = 1
} else if idx >= v.Size() {
idx = v.Size()
for p := idx; p < v.len-1; p++ {
v.data[p] = v.data[p+1]
}
v.len--
if v.cap-v.len >= 2^16 {
//容量和实际使用差值超过2^16时,容量直接减去2^16
v.cap -= 2 ^ 16
tmp := make([]interface{}, v.cap, v.cap)
copy(tmp, v.data)
v.data = tmp
} else if v.len*2 < v.cap {
//实际使用长度是容量的一半时,进行折半缩容
v.cap /= 2
tmp := make([]interface{}, v.cap, v.cap)
copy(tmp, v.data)
v.data = tmp
}
es := append([]interface{}{}, v.data[:idx-1]...)
v.data = append(es, v.data[idx:]...)
v.end--
v.mutex.Unlock()
}
@ -292,22 +352,27 @@ func (v *vector) Erase(idx int) {
// 以vector向量容器做接收者
// 将vector容器中不使用空间释放掉
// 将该容器中的泛型切片中的所有元素顺序逆转
//@auth hlccd 2021-07-4
//@receiver v *vector 接受者vector的指针
//@param nil
//@return nil
func (v *vector) Reverse() {
if v == nil {
return
v = New()
}
v.mutex.Lock()
if v.end > 0 {
v.data = v.data[:v.end]
} else {
v.data = make([]interface{}, 0, 0)
if v.data == nil {
//data不存在,新建一个
v.data = make([]interface{}, 1, 1)
v.len = 0
v.cap = 1
} else if v.len < v.cap {
//释放未使用的空间
tmp := make([]interface{}, v.len, v.len)
copy(tmp, v.data)
v.data = tmp
}
for i := 0; i < v.end/2; i++ {
v.data[i], v.data[v.end-i-1] = v.data[v.end-i-1], v.data[i]
for i := uint64(0); i < v.len/2; i++ {
v.data[i], v.data[v.len-i-1] = v.data[v.len-i-1], v.data[i]
}
v.mutex.Unlock()
}
@ -319,13 +384,12 @@ func (v *vector) Reverse() {
// 当idx不在容器中泛型切片的使用范围内
// 即当idx小于0或者idx大于容器所含有的元素个数时返回nil
// 反之返回对应位置的元素
// idx从0计算
//@auth hlccd 2021-07-4
//@receiver v *vector 接受者vector的指针
//@param idx int 待查找元素的位置
//@param idx uint64 待查找元素的位置(下标从0开始)
//@return e interface{} 从容器中查找的第idx位元素
func (v *vector) At(idx int) (e interface{}) {
func (v *vector) At(idx uint64) (e interface{}) {
if v == nil {
v=New()
return nil
}
v.mutex.Lock()
@ -347,12 +411,12 @@ func (v *vector) At(idx int) (e interface{}) {
// 以vector向量容器做接收者
// 返回该容器的第一个元素
// 若该容器当前为空,则返回nil
//@auth hlccd 2021-07-4
//@receiver v *vector 接受者vector的指针
//@param nil
//@return e interface{} 容器的第一个元素
func (v *vector) Front() (e interface{}) {
if v == nil {
v=New()
return nil
}
v.mutex.Lock()
@ -376,11 +440,12 @@ func (v *vector) Front() (e interface{}) {
//@return e interface{} 容器的最后一个元素
func (v *vector) Back() (e interface{}) {
if v == nil {
v=New()
return nil
}
v.mutex.Lock()
if v.Size() > 0 {
e = v.data[v.end-1]
e = v.data[v.len-1]
v.mutex.Unlock()
return e
}