mirror of
https://github.com/hlccd/goSTL.git
synced 2025-01-19 06:19:32 +08:00
新增了bitmap实现
This commit is contained in:
parent
68920f57fd
commit
6c287f0116
188
goSTL/data_structure/bitmap/bitmap.go
Normal file
188
goSTL/data_structure/bitmap/bitmap.go
Normal file
@ -0,0 +1,188 @@
|
|||||||
|
package bitmap
|
||||||
|
|
||||||
|
//@Title bitmap
|
||||||
|
//@Description
|
||||||
|
// bitmap位图容器包
|
||||||
|
// 内部使用uint64切片进行存储
|
||||||
|
// 由于数字在计算机内部存储时采用多个bit组成一个字符
|
||||||
|
// 而一bit只有1和0两个情况,所以也可以使用一个bit表示任意一位存在
|
||||||
|
// 该数据结构主要可以进行过滤去重、标注是否存在、快速排序的功能
|
||||||
|
|
||||||
|
//bitmap位图结构体
|
||||||
|
//包含其用于存储的uint64元素切片
|
||||||
|
//选用uint64是为了更多的利用bit位
|
||||||
|
|
||||||
|
type bitmap struct {
|
||||||
|
bits []uint64
|
||||||
|
}
|
||||||
|
|
||||||
|
//bitmap位图容器接口
|
||||||
|
//存放了bitmap容器可使用的函数
|
||||||
|
//对应函数介绍见下方
|
||||||
|
|
||||||
|
type bitmaper interface {
|
||||||
|
Insert(num uint) //在num位插入元素
|
||||||
|
Delete(num uint) //删除第num位
|
||||||
|
Check(num uint) (b bool) //检查第num位是否有元素
|
||||||
|
All() (nums []uint) //返回所有存储的元素的下标
|
||||||
|
Clear() //清空
|
||||||
|
}
|
||||||
|
|
||||||
|
//@title New
|
||||||
|
//@description
|
||||||
|
// 新建一个bitmap位图容器并返回
|
||||||
|
// 初始bitmap的切片数组为空
|
||||||
|
//@receiver nil
|
||||||
|
//@param nil
|
||||||
|
//@return bm *bitmap 新建的bitmap指针
|
||||||
|
func New() (bm *bitmap) {
|
||||||
|
return &bitmap{
|
||||||
|
bits: make([]uint64, 0, 0),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//@title Insert
|
||||||
|
//@description
|
||||||
|
// 以bitmap位图容器做接收者
|
||||||
|
// 向位图中第num位插入一个元素(下标从0开始)
|
||||||
|
// 当num大于当前所能存储的位范围时,需要进行扩增
|
||||||
|
// 若要插入的位比冗余的多不足2^16即1024*64时,则新增1024个uint64
|
||||||
|
// 否则则直接增加到可以容纳第num位的位置,以此可以提高冗余量,避免多次增加
|
||||||
|
//@receiver bm *bitmap 接受者bitmap的指针
|
||||||
|
//@param num int 待插入的位的下标
|
||||||
|
//@return nil
|
||||||
|
func (bm *bitmap) Insert(num uint) {
|
||||||
|
//bm不存在时直接结束
|
||||||
|
if bm == nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
//开始插入
|
||||||
|
if num/64+1 > uint(len(bm.bits)) {
|
||||||
|
//当前冗余量小于num位,需要扩增
|
||||||
|
var tmp []uint64
|
||||||
|
//通过冗余扩增减少扩增次数
|
||||||
|
if num/64+1 < uint(len(bm.bits)+1024) {
|
||||||
|
//入的位比冗余的多不足2^16即1024*64时,则新增1024个uint64
|
||||||
|
tmp = make([]uint64, len(bm.bits)+1024)
|
||||||
|
} else {
|
||||||
|
//直接增加到可以容纳第num位的位置
|
||||||
|
tmp = make([]uint64, num/64+1)
|
||||||
|
}
|
||||||
|
//将原有元素复制到新增的切片内,并将bm所指向的修改为扩增后的
|
||||||
|
copy(tmp, bm.bits)
|
||||||
|
bm.bits = tmp
|
||||||
|
}
|
||||||
|
//将第num位设为1即实现插入
|
||||||
|
bm.bits[num/64] ^= 1 << (num % 64)
|
||||||
|
}
|
||||||
|
|
||||||
|
//@title Delete
|
||||||
|
//@description
|
||||||
|
// 以bitmap位图容器做接收者
|
||||||
|
// 向位图中第num位删除一个元素(下标从0开始)
|
||||||
|
// 当num大于当前所能存储的位范围时,直接结束即可
|
||||||
|
// 删除完成后对切片最后存储的uint64进行判断是否大于1,若大于1则不做缩容
|
||||||
|
// 若等于0则可以进行缩容
|
||||||
|
// 对于缩容而言,从后往前遍历判断最后有多少个连续的0,即可以删除的多少组
|
||||||
|
// 若可删除的组大于总组数的一半则进行删除,否则则当作冗余量即可
|
||||||
|
// 若可删除的组数超过1024个时,则先删除1024个
|
||||||
|
//@receiver bm *bitmap 接受者bitmap的指针
|
||||||
|
//@param num int 待删除的位的下标
|
||||||
|
//@return nil
|
||||||
|
func (bm *bitmap) Delete(num uint) {
|
||||||
|
//bm不存在时直接结束
|
||||||
|
if bm == nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
//num超出范围,直接结束
|
||||||
|
if num/64+1 > uint(len(bm.bits)) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
//将第num位设为0
|
||||||
|
bm.bits[num/64] &^= 1 << (num % 64)
|
||||||
|
if bm.bits[len(bm.bits)-1] == 0 {
|
||||||
|
//最后一组为0,可能进行缩容
|
||||||
|
//从后往前遍历判断可缩容内容是否小于总组数
|
||||||
|
i := len(bm.bits) - 1
|
||||||
|
for ; i >= 0; i-- {
|
||||||
|
if bm.bits[i] == 0 && i!=len(bm.bits)-256{
|
||||||
|
continue
|
||||||
|
} else {
|
||||||
|
//不为0或到1024个时即可返回
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if i <= len(bm.bits)/2 || i==len(bm.bits)-256 {
|
||||||
|
//小于总组数一半或超过1023个,进行缩容
|
||||||
|
bm.bits = bm.bits[:i+1]
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//@title Check
|
||||||
|
//@description
|
||||||
|
// 以bitmap位图容器做接收者
|
||||||
|
// 检验第num位在位图中是否存在
|
||||||
|
// 当num大于当前所能存储的位范围时,直接返回false
|
||||||
|
// 否则判断第num为是否为1,为1返回true,否则返回false
|
||||||
|
//@receiver bm *bitmap 接受者bitmap的指针
|
||||||
|
//@param num int 待检测位的下标
|
||||||
|
//@return b bool 第num位存在于位图中
|
||||||
|
func (bm *bitmap) Check(num uint) (b bool) {
|
||||||
|
//bm不存在时直接返回false并结束
|
||||||
|
if bm == nil {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
//num超出范围,直接返回false并结束
|
||||||
|
if num/64+1 > uint(len(bm.bits)) {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
//判断第num是否为1,为1返回true,否则为false
|
||||||
|
if bm.bits[num/64]&(1<<num%64) > 0 {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
//@title All
|
||||||
|
//@description
|
||||||
|
// 以bitmap位图容器做接收者
|
||||||
|
// 返回所有在位图中存在的元素的下标
|
||||||
|
// 返回的下标是单调递增序列
|
||||||
|
//@receiver bm *bitmap 接受者bitmap的指针
|
||||||
|
//@param nil
|
||||||
|
//@return nums []uint 所有在位图中存在的元素的下标集合
|
||||||
|
func (bm *bitmap) All() (nums []uint) {
|
||||||
|
//对要返回的集合进行初始化,以避免返回nil
|
||||||
|
nums=make([]uint,0,0)
|
||||||
|
//bm不存在时直接返回并结束
|
||||||
|
if bm == nil {
|
||||||
|
return nums
|
||||||
|
}
|
||||||
|
//分组遍历判断某下标的元素是否存在于位图中,即其值是否为1
|
||||||
|
for j := 0; j < len(bm.bits); j++ {
|
||||||
|
for i := 0; i < 64; i++ {
|
||||||
|
if bm.bits[j]&(1<<i) > 0 {
|
||||||
|
//该元素存在,添加入结果集合内
|
||||||
|
nums = append(nums, uint(j*64+i))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return nums
|
||||||
|
}
|
||||||
|
|
||||||
|
//@title Clear
|
||||||
|
//@description
|
||||||
|
// 以bitmap位图容器做接收者
|
||||||
|
// 清空位图
|
||||||
|
//@receiver bm *bitmap 接受者bitmap的指针
|
||||||
|
//@param nil
|
||||||
|
//@return nums []uint 所有在位图中存在的元素的下标集合
|
||||||
|
func (bm *bitmap) Clear() {
|
||||||
|
if bm == nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
bm.bits = make([]uint64, 0, 0)
|
||||||
|
}
|
@ -8,9 +8,11 @@ package vector
|
|||||||
// 通过interface实现泛型
|
// 通过interface实现泛型
|
||||||
// 可接纳不同类型的元素
|
// 可接纳不同类型的元素
|
||||||
// 但建议在同一个vector中使用相同类型的元素
|
// 但建议在同一个vector中使用相同类型的元素
|
||||||
// 可通过配合比较器competitor和迭代器iterator对该vector容器进行排序或查找
|
// 可通过配合比较器competitor和迭代器iterator对该vector容器进行排序查找或遍历
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"github.com/hlccd/goSTL/utils/comparator"
|
||||||
|
"github.com/hlccd/goSTL/utils/iterator"
|
||||||
"sync"
|
"sync"
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -32,17 +34,19 @@ type vector struct {
|
|||||||
//对应函数介绍见下方
|
//对应函数介绍见下方
|
||||||
|
|
||||||
type vectorer interface {
|
type vectorer interface {
|
||||||
Size() (num int) //返回vector的长度
|
Iterator() *Iterator.Iterator //返回一个包含vector所有元素的迭代器
|
||||||
Clear() //清空vector
|
Sort(Cmp ...comparator.Comparator) //利用比较器对其进行排序
|
||||||
Empty() (b bool) //返回vector是否为空,为空则返回true反之返回false
|
Size() (num int) //返回vector的长度
|
||||||
PushBack(e interface{}) //向vector末尾插入一个元素
|
Clear() //清空vector
|
||||||
PopBack() //弹出vector末尾元素
|
Empty() (b bool) //返回vector是否为空,为空则返回true反之返回false
|
||||||
Insert(idx int, e interface{}) //向vector第idx的位置插入元素e,同时idx后的其他元素向后退一位
|
PushBack(e interface{}) //向vector末尾插入一个元素
|
||||||
Erase(idx int) //删除vector的第idx个元素
|
PopBack() //弹出vector末尾元素
|
||||||
Reverse() //逆转vector中的数据顺序
|
Insert(idx int, e interface{}) //向vector第idx的位置插入元素e,同时idx后的其他元素向后退一位
|
||||||
At(idx int) (e interface{}) //返回vector的第idx的元素
|
Erase(idx int) //删除vector的第idx个元素
|
||||||
Front() (e interface{}) //返回vector的第一个元素
|
Reverse() //逆转vector中的数据顺序
|
||||||
Back() (e interface{}) //返回vector的最后一个元素
|
At(idx int) (e interface{}) //返回vector的第idx的元素
|
||||||
|
Front() (e interface{}) //返回vector的第一个元素
|
||||||
|
Back() (e interface{}) //返回vector的最后一个元素
|
||||||
}
|
}
|
||||||
|
|
||||||
//@title New
|
//@title New
|
||||||
@ -55,12 +59,61 @@ type vectorer interface {
|
|||||||
//@return v *vector 新建的vector指针
|
//@return v *vector 新建的vector指针
|
||||||
func New() (v *vector) {
|
func New() (v *vector) {
|
||||||
return &vector{
|
return &vector{
|
||||||
data: make([]interface{}, 1),
|
data: make([]interface{}, 1, 1),
|
||||||
end: 0,
|
end: 0,
|
||||||
mutex: sync.Mutex{},
|
mutex: sync.Mutex{},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//@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.mutex.Lock()
|
||||||
|
if v.end > 0 {
|
||||||
|
v.data = v.data[:v.end]
|
||||||
|
} else {
|
||||||
|
v.data = make([]interface{}, 1, 1)
|
||||||
|
}
|
||||||
|
i = Iterator.New(&v.data)
|
||||||
|
v.mutex.Unlock()
|
||||||
|
return i
|
||||||
|
}
|
||||||
|
|
||||||
|
//@title Sort
|
||||||
|
//@description
|
||||||
|
// 以vector向量容器做接收者
|
||||||
|
// 将vector向量容器中不使用空间释放掉
|
||||||
|
// 对元素中剩余的部分进行排序
|
||||||
|
//@receiver v *vector 接受者vector的指针
|
||||||
|
//@param Cmp ...comparator.Comparator 比较函数
|
||||||
|
//@return i *iterator.Iterator 新建的Iterator迭代器指针
|
||||||
|
func (v *vector) Sort(Cmp ...comparator.Comparator) {
|
||||||
|
if v == nil {
|
||||||
|
v.data = make([]interface{}, 1, 1)
|
||||||
|
}
|
||||||
|
v.mutex.Lock()
|
||||||
|
if v.end > 0 {
|
||||||
|
v.data = v.data[:v.end]
|
||||||
|
} else {
|
||||||
|
v.data = make([]interface{}, 0, 0)
|
||||||
|
}
|
||||||
|
if len(Cmp) == 0 {
|
||||||
|
comparator.Sort(&v.data)
|
||||||
|
} else {
|
||||||
|
comparator.Sort(&v.data, Cmp[0])
|
||||||
|
}
|
||||||
|
v.mutex.Unlock()
|
||||||
|
}
|
||||||
|
|
||||||
//@title Size
|
//@title Size
|
||||||
//@description
|
//@description
|
||||||
|
Loading…
x
Reference in New Issue
Block a user