From 6c287f0116adb86ac088a8637d1d220daaeee5e7 Mon Sep 17 00:00:00 2001 From: hlccd <56643462+hlccd@users.noreply.github.com> Date: Tue, 19 Oct 2021 16:45:44 +0800 Subject: [PATCH] =?UTF-8?q?=E6=96=B0=E5=A2=9E=E4=BA=86bitmap=E5=AE=9E?= =?UTF-8?q?=E7=8E=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- goSTL/data_structure/bitmap/bitmap.go | 188 ++++++++++++++++++++++++++ goSTL/data_structure/vector/vector.go | 79 +++++++++-- 2 files changed, 254 insertions(+), 13 deletions(-) create mode 100644 goSTL/data_structure/bitmap/bitmap.go diff --git a/goSTL/data_structure/bitmap/bitmap.go b/goSTL/data_structure/bitmap/bitmap.go new file mode 100644 index 0000000..60ed4c6 --- /dev/null +++ b/goSTL/data_structure/bitmap/bitmap.go @@ -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< 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< 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) +} diff --git a/goSTL/data_structure/vector/vector.go b/goSTL/data_structure/vector/vector.go index f333363..f7a7970 100644 --- a/goSTL/data_structure/vector/vector.go +++ b/goSTL/data_structure/vector/vector.go @@ -8,9 +8,11 @@ package vector // 通过interface实现泛型 // 可接纳不同类型的元素 // 但建议在同一个vector中使用相同类型的元素 -// 可通过配合比较器competitor和迭代器iterator对该vector容器进行排序或查找 +// 可通过配合比较器competitor和迭代器iterator对该vector容器进行排序查找或遍历 import ( + "github.com/hlccd/goSTL/utils/comparator" + "github.com/hlccd/goSTL/utils/iterator" "sync" ) @@ -32,17 +34,19 @@ type vector struct { //对应函数介绍见下方 type vectorer interface { - Size() (num int) //返回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个元素 - Reverse() //逆转vector中的数据顺序 - At(idx int) (e interface{}) //返回vector的第idx的元素 - Front() (e interface{}) //返回vector的第一个元素 - Back() (e interface{}) //返回vector的最后一个元素 + Iterator() *Iterator.Iterator //返回一个包含vector所有元素的迭代器 + Sort(Cmp ...comparator.Comparator) //利用比较器对其进行排序 + Size() (num int) //返回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个元素 + Reverse() //逆转vector中的数据顺序 + At(idx int) (e interface{}) //返回vector的第idx的元素 + Front() (e interface{}) //返回vector的第一个元素 + Back() (e interface{}) //返回vector的最后一个元素 } //@title New @@ -55,12 +59,61 @@ type vectorer interface { //@return v *vector 新建的vector指针 func New() (v *vector) { return &vector{ - data: make([]interface{}, 1), + data: make([]interface{}, 1, 1), end: 0, 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 //@description