gitee.com/quant1x/engine@v1.8.4/labs/bitmap.go (about) 1 package labs 2 3 import ( 4 "fmt" 5 "strings" 6 ) 7 8 const ( 9 bitSize = 8 10 ) 11 12 var bitmask = []byte{1, 1 << 1, 1 << 2, 1 << 3, 1 << 4, 1 << 5, 1 << 6, 1 << 7} 13 14 // Bitmap 首字母小写 只能调用 工厂函数 创建 15 type Bitmap struct { 16 bits []byte 17 bitCount uint64 // 已填入数字的数量 18 capacity uint64 // 容量 19 } 20 21 // NewBitmap 创建工厂函数 22 func NewBitmap(maxnum uint64) *Bitmap { 23 return &Bitmap{bits: make([]byte, (maxnum+7)/bitSize), bitCount: 0, capacity: maxnum} 24 } 25 26 // Set 填入数字 27 func (this *Bitmap) Set(num uint64) { 28 byteIndex, bitPos := this.offset(num) 29 // 1 左移 bitPos 位 进行 按位或 (置为 1) 30 this.bits[byteIndex] |= bitmask[bitPos] 31 this.bitCount++ 32 } 33 34 // Reset 清除填入的数字 35 func (this *Bitmap) Reset(num uint64) { 36 byteIndex, bitPos := this.offset(num) 37 // 重置为空位 (重置为 0) 38 this.bits[byteIndex] &= ^bitmask[bitPos] 39 this.bitCount-- 40 } 41 42 // Test 数字是否在位图中 43 func (this *Bitmap) Test(num uint64) bool { 44 byteIndex := num / bitSize 45 if byteIndex >= uint64(len(this.bits)) { 46 return false 47 } 48 bitPos := num % bitSize 49 // 右移 bitPos 位 和 1 进行 按位与 50 return !(this.bits[byteIndex]&bitmask[bitPos] == 0) 51 } 52 53 func (this *Bitmap) offset(num uint64) (byteIndex uint64, bitPos byte) { 54 byteIndex = num / bitSize // 字节索引 55 if byteIndex >= uint64(len(this.bits)) { 56 panic(fmt.Sprintf(" runtime error: index value %d out of range", byteIndex)) 57 return 58 } 59 bitPos = byte(num % bitSize) // bit位置 60 return byteIndex, bitPos 61 } 62 63 // Size 位图的容量 64 func (this *Bitmap) Size() uint64 { 65 return uint64(len(this.bits) * bitSize) 66 } 67 68 // IsEmpty 是否空位图 69 func (this *Bitmap) IsEmpty() bool { 70 return this.bitCount == 0 71 } 72 73 // IsFully 是否已填满 74 func (this *Bitmap) IsFully() bool { 75 return this.bitCount == this.capacity 76 } 77 78 // Count 已填入的数字个数 79 func (this *Bitmap) Count() uint64 { 80 return this.bitCount 81 } 82 83 // GetData 获取填入的数字切片 84 func (this *Bitmap) GetData() []uint64 { 85 var data []uint64 86 count := this.Size() 87 for index := uint64(0); index < count; index++ { 88 if this.Test(index) { 89 data = append(data, index) 90 } 91 } 92 return data 93 } 94 95 func (this *Bitmap) String() string { 96 var sb strings.Builder 97 for index := len(this.bits) - 1; index >= 0; index-- { 98 sb.WriteString(byteToBinaryString(this.bits[index])) 99 sb.WriteString(" ") 100 } 101 return sb.String() 102 } 103 104 func byteToBinaryString(data byte) string { 105 var sb strings.Builder 106 for index := 0; index < bitSize; index++ { 107 if (bitmask[7-index] & data) == 0 { 108 sb.WriteString("0") 109 } else { 110 sb.WriteString("1") 111 } 112 } 113 return sb.String() 114 }