bitmap commit
parent
8ff3e7c865
commit
b9d0051e56
|
@ -0,0 +1,12 @@
|
|||
# Owner
|
||||
lh1814
|
||||
|
||||
# Author
|
||||
lh1814
|
||||
|
||||
# Reviewer
|
||||
|
||||
|
||||
# Description
|
||||
算法和数据结构应用小工具
|
||||
bitmap ---------------> lh1814
|
|
@ -0,0 +1,192 @@
|
|||
package bitmap
|
||||
|
||||
import (
|
||||
"encoding/base64"
|
||||
"sync"
|
||||
)
|
||||
|
||||
/*
|
||||
@Author: by LH
|
||||
@date: 2019-06-12
|
||||
@function:位图算法go语言版本类型抽象
|
||||
*/
|
||||
const byteBitLength = 8 //一个字节的位数,也是一个uint8类型的位数
|
||||
|
||||
type BitMap struct {
|
||||
value []uint8
|
||||
//bit uint64
|
||||
mu sync.RWMutex
|
||||
count uint64
|
||||
}
|
||||
|
||||
func NewBitMapFromBase64String(s string) (*BitMap, error) { //不要太长比较好
|
||||
decodeBytes, e := base64.StdEncoding.DecodeString(s)
|
||||
if e != nil {
|
||||
return nil, e
|
||||
}
|
||||
|
||||
return &BitMap{
|
||||
value: decodeBytes,
|
||||
count: count(decodeBytes),
|
||||
mu: sync.RWMutex{},
|
||||
}, nil
|
||||
}
|
||||
|
||||
//统计1数量
|
||||
func count(m []byte) (r uint64) {
|
||||
for _, v := range m {
|
||||
for i := 0; i < byteBitLength; i++ {
|
||||
if ByteIndexIsOne(v, i) {
|
||||
r++
|
||||
}
|
||||
}
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
//从string加载
|
||||
func NewBitMapFromString(s string) *BitMap {
|
||||
|
||||
return &BitMap{
|
||||
value: []byte(s),
|
||||
mu: sync.RWMutex{},
|
||||
count: count([]byte(s)),
|
||||
}
|
||||
}
|
||||
|
||||
func (b *BitMap) Reset() {
|
||||
b.mu.Lock()
|
||||
defer b.mu.Unlock()
|
||||
b.value = make([]uint8, 0)
|
||||
b.count = 0
|
||||
}
|
||||
|
||||
func (b *BitMap) Count() uint64 {
|
||||
return b.count
|
||||
}
|
||||
|
||||
//获取当前位数长度
|
||||
func (b *BitMap) Length() int {
|
||||
b.mu.RLock()
|
||||
defer b.mu.RUnlock()
|
||||
return len(b.value) * byteBitLength
|
||||
}
|
||||
|
||||
//func (b *BitMap) BitLength() uint64 {
|
||||
// return b.bit
|
||||
//}
|
||||
|
||||
//判断指定位置是否为1
|
||||
func (b *BitMap) IsBit(index int) (r bool) {
|
||||
b.mu.RLock()
|
||||
defer b.mu.RUnlock()
|
||||
if index < 0 || index >= len(b.value)*byteBitLength { //边界情况
|
||||
return
|
||||
}
|
||||
x := index / byteBitLength
|
||||
y := index % byteBitLength
|
||||
if ByteIndexIsOne(b.value[x], y) {
|
||||
r = true
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
//value数组增加num个长度
|
||||
func (b *BitMap) addLength(n int) {
|
||||
for i := 0; i < n; i++ {
|
||||
b.value = append(b.value, 0)
|
||||
}
|
||||
}
|
||||
|
||||
//设置指定位置为1
|
||||
func (b *BitMap) SetBit(index int) {
|
||||
if index < 0 {
|
||||
return
|
||||
}
|
||||
|
||||
b.mu.Lock()
|
||||
defer b.mu.Unlock()
|
||||
if index >= len(b.value)*byteBitLength { //需要加长度
|
||||
b.addLength(index/byteBitLength + 1 - len(b.value))
|
||||
}
|
||||
|
||||
arrIndex := index / byteBitLength
|
||||
bitIndex := index % byteBitLength
|
||||
|
||||
if !ByteIndexIsOne(b.value[arrIndex], bitIndex) { //不为1时设置为1
|
||||
b.value[arrIndex] ^= 128 >> bitIndex
|
||||
b.count++
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
//设置指定位置为0
|
||||
func (b *BitMap) CancelBit(index int) {
|
||||
if index < 0 || index >= len(b.value)*byteBitLength {
|
||||
return
|
||||
}
|
||||
|
||||
arrIndex := index / byteBitLength
|
||||
bitIndex := index % byteBitLength
|
||||
|
||||
if ByteIndexIsOne(b.value[arrIndex], bitIndex) { //为1时设置为0
|
||||
b.mu.Lock()
|
||||
defer b.mu.Unlock()
|
||||
b.value[arrIndex] ^= 128 >> bitIndex
|
||||
b.count--
|
||||
}
|
||||
}
|
||||
|
||||
//base64转化为string
|
||||
func (b *BitMap) Base64String() string {
|
||||
b.mu.RLock()
|
||||
defer b.mu.RUnlock()
|
||||
return base64.StdEncoding.EncodeToString(b.value)
|
||||
}
|
||||
|
||||
//转 string
|
||||
func (b *BitMap) String() string {
|
||||
b.mu.RLock()
|
||||
defer b.mu.RUnlock()
|
||||
return string(b.value)
|
||||
}
|
||||
|
||||
//判断一个byte的指定位置是否为1,顺序为从高位到低位下标分别为0->7
|
||||
func ByteIndexIsOne(a byte, index int) bool {
|
||||
if index < 0 || index >= byteBitLength {
|
||||
return false
|
||||
}
|
||||
|
||||
//t := a
|
||||
//t ^= 128 >> index //判断t是否和a相等
|
||||
a <<= index
|
||||
a >>= 7
|
||||
if a == 0 {
|
||||
return false
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
func ByteReverse(b byte) byte {
|
||||
for i := 0; i < 4; i++ {
|
||||
if (b&(128>>i))>>(7-i) != (b&(1<<i))>>i {
|
||||
b ^= 128 >> i
|
||||
b ^= 1 << i
|
||||
}
|
||||
}
|
||||
return b
|
||||
}
|
||||
|
||||
//>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>以下函数为测试,封装好类型的在上面<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
|
||||
//从第0位开始判断
|
||||
func GetBit(s []uint8, index int) (r bool) {
|
||||
if index < 0 || index >= len(s)*byteBitLength { //边界情况
|
||||
return
|
||||
}
|
||||
a := index / byteBitLength
|
||||
b := index % byteBitLength
|
||||
if ByteIndexIsOne(s[a], b) {
|
||||
r = true
|
||||
}
|
||||
return
|
||||
}
|
|
@ -0,0 +1,41 @@
|
|||
package bitmap
|
||||
|
||||
import (
|
||||
"testing"
|
||||
)
|
||||
|
||||
/*
|
||||
@Author: by LH
|
||||
@date: 2020/7/21
|
||||
@function:
|
||||
*/
|
||||
|
||||
func TestBitMap(t *testing.T) {
|
||||
var b BitMap
|
||||
|
||||
b.SetBit(1)
|
||||
b.SetBit(3)
|
||||
b.SetBit(5)
|
||||
|
||||
if !b.IsBit(1) || !b.IsBit(3) || !b.IsBit(5) {
|
||||
t.Fatal("b 1 3 5 should be true")
|
||||
}
|
||||
|
||||
if b.Count() != 3 {
|
||||
t.Fatal("b length should be 3")
|
||||
}
|
||||
|
||||
b.Base64String()
|
||||
c, e := NewBitMapFromBase64String(b.Base64String())
|
||||
if e != nil {
|
||||
t.Fatal(e)
|
||||
}
|
||||
if !c.IsBit(1) || !c.IsBit(3) || !c.IsBit(5) {
|
||||
t.Fatal("c 1 3 5 should be true")
|
||||
}
|
||||
|
||||
if c.Count() != 3 {
|
||||
t.Fatal("c length should be 3")
|
||||
}
|
||||
|
||||
}
|
Loading…
Reference in New Issue