BitMap

BitMap(位图)是一种用于存储和操作二进制位(0和1)的数据结构。它将每个元素表示为一个二进制位,可以使用位运算对位图进行高效的插入、删除和查询操作。

BitMap常用于以下场景:

  1. 去重:可以使用BitMap来判断某个元素是否存在,例如判断一个数字是否在一个大数据集中出现过。
  2. 排序:可以使用BitMap来对一组数字进行排序,通过设置对应位置的位来表示数字的出现与否,然后按位进行遍历得到排序结果。
  3. 压缩存储:当需要存储大量的布尔类型数据时,使用BitMap可以大幅减少存储空间,因为每个位只占用1比特。

在使用BitMap时,通常需要将数据映射到BitMap中的位位置。例如,对于一个整数集合,可以将每个整数映射到BitMap中的对应位上。设置位为1表示该整数存在,位为0表示该整数不存在。

以下是使用BitMap的基本操作:

  1. 设置位(Set):将指定位置的位设置为1。
  2. 清除位(Clear):将指定位置的位设置为0。
  3. 查询位(Get):获取指定位置的位的值(0或1)。
  4. 取反位(Flip):将指定位置的位的值取反(0变为1,1变为0)。
  5. 统计位(Count):计算BitMap中值为1的位的个数。
  6. 按位与(AND):将两个BitMap进行按位与操作。
  7. 按位或(OR):将两个BitMap进行按位或操作。
  8. 按位异或(XOR):将两个BitMap进行按位异或操作。

需要注意的是,BitMap适用于数据集较小且值范围可控的情况,因为BitMap的大小直接取决于数据集的最大值。当数据集较大时,BitMap可能会占用大量的内存。

在Go语言中,可以使用内置的位运算操作符和数据类型(如uint64)来实现BitMap。通过将整数映射到BitMap的位上,可以进行高效的位操作。具体实现可以根据具体需求进行设计。

package main

import "fmt"

func main() {
    // 假设需要表示的数据范围为 0 到 99
    maxValue := 100
    // 创建一个长度为 (maxValue/8)+1 的切片用于存储 BitMap
    bitmap := make([]byte, (maxValue/8)+1)
    // 设置位
    SetBit(bitmap, 5)
    SetBit(bitmap, 10)
    SetBit(bitmap, 20)
    // 查询位
    fmt.Println(GetBit(bitmap, 5))  // 输出: true
    fmt.Println(GetBit(bitmap, 10)) // 输出: true
    fmt.Println(GetBit(bitmap, 15)) // 输出: false
    // 清除位
    ClearBit(bitmap, 10)
    // 查询位
    fmt.Println(GetBit(bitmap, 10)) // 输出: false
    // 输出bitmap的二进制
    fmt.Printf("%08b\n", bitmap) // 输出: [00100000 00000000 00010000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000]
}

// SetBit 设置位
func SetBit(bitmap []byte, num int) {
    index := num / 8
    offset := num % 8
    bitmap[index] |= (1 << uint(offset))
}

// ClearBit 清除位
func ClearBit(bitmap []byte, num int) {
    index := num / 8
    offset := num % 8
    bitmap[index] &= ^(1 << uint(offset))
}

// GetBit 查询位
func GetBit(bitmap []byte, num int) bool {
    index := num / 8
    offset := num % 8
    return (bitmap[index] & (1 << uint(offset))) != 0
}

再看一个例子

package main

import "fmt"

type BitMap []uint64

func NewBitMap(size int) BitMap {
   numWords := size/64 + 1
   return make(BitMap, numWords)
}

func (bitmap BitMap) Set(index int) {
   wordIndex := index / 64
   bitIndex := index % 64
   bitmap[wordIndex] |= 1 << bitIndex
}

func (bitmap BitMap) Clear(index int) {
   wordIndex := index / 64
   bitIndex := index % 64
   bitmap[wordIndex] &^= 1 << bitIndex
}

func (bitmap BitMap) Get(index int) bool {
   wordIndex := index / 64
   bitIndex := index % 64
   return (bitmap[wordIndex] & (1 << bitIndex)) != 0
}

func (bitmap BitMap) Flip(index int) {
   wordIndex := index / 64
   bitIndex := index % 64
   bitmap[wordIndex] ^= 1 << bitIndex
}

func (bitmap BitMap) Count() int {
   count := 0
   for _, word := range bitmap {
       for word != 0 {
           count += int(word & 1)
           word >>= 1
       }
   }
   return count
}

func (bitmap BitMap) And(other BitMap) BitMap {
   result := make(BitMap, len(bitmap))
   for i := range bitmap {
       result[i] = bitmap[i] & other[i]
   }
   return result
}

func (bitmap BitMap) Or(other BitMap) BitMap {
   result := make(BitMap, len(bitmap))
   for i := range bitmap {
       result[i] = bitmap[i] | other[i]
   }
   return result
}

func (bitmap BitMap) Xor(other BitMap) BitMap {
   result := make(BitMap, len(bitmap))
   for i := range bitmap {
       result[i] = bitmap[i] ^ other[i]
   }
   return result
}

func main() {
   bitmap := NewBitMap(128)

   // 设置位
   bitmap.Set(5)
   bitmap.Set(10)
   bitmap.Set(20)

   // 清除位
   bitmap.Clear(10)

   // 查询位
   fmt.Println("位 5 的值:", bitmap.Get(5))
   fmt.Println("位 10 的值:", bitmap.Get(10))
   fmt.Println("位 20 的值:", bitmap.Get(20))

   // 取反位
   bitmap.Flip(5)
   bitmap.Flip(15)

   // 统计位
   count := bitmap.Count()
   fmt.Println("位为 1 的个数:", count)

   // 创建另一个 BitMap
   otherBitmap := NewBitMap(128)
   otherBitmap.Set(10)
   otherBitmap.Set(15)

   // 按位与
   andResult := bitmap.And(otherBitmap)
   fmt.Println("按位与结果:", andResult)

   // 按位或
   orResult := bitmap.Or(otherBitmap)
   fmt.Println("按位或结果:", orResult)

   // 按位异或
   xorResult := bitmap.Xor(otherBitmap)
   fmt.Println("按位异或结果:", xorResult)
}

结果为

位 5 的值: true
位 10 的值: false
位 20 的值: true
位为 1 的个数: 2
按位与结果: [32768 0 0]
按位或结果: [1082368 0 0]
按位异或结果: [1049600 0 0]
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值