Go语言实现bitmap算法

有关bitmap算法的介绍资料网上很多,这里不赘述,各种语言的实现也不少,但是Go语言版的bitmap不多,本文就来写一个Go版的bitmap实现。

首先创建一个 bitmap.go 文件,定义一个bitmap结构体,再提供一些操作方法。详细代码如下:

package bitmap

import (
    "fmt"
    "strings"
)

const (
    bitSize = 8
)

var bitmask = []byte{1, 1 << 1, 1 << 2, 1 << 3, 1 << 4, 1 << 5, 1 << 6, 1 << 7}
// 首字母小写 只能调用 工厂函数 创建
type bitmap struct {
    bits     []byte
    bitCount uint64 // 已填入数字的数量
    capacity uint64 // 容量
}
// 创建工厂函数
func NewBitmap(maxnum uint64) *bitmap {
    return &bitmap{bits: make([]byte, (maxnum+7)/bitSize), bitCount: 0, capacity: maxnum}
}

// 填入数字
func (this *bitmap) Set(num uint64) {
    byteIndex, bitPos := this.offset(num)
    // 1 左移 bitPos 位 进行 按位或 (置为 1)
    this.bits[byteIndex] |= bitmask[bitPos]
    this.bitCount++
}

// 清除填入的数字
func (this *bitmap) Reset(num uint64) {
    byteIndex, bitPos := this.offset(num)
    // 重置为空位 (重置为 0)
    this.bits[byteIndex] &= ^bitmask[bitPos]
    this.bitCount--
}

// 数字是否在位图中
func (this *bitmap) Test(num uint64) bool {
    byteIndex := num / bitSize
    if byteIndex >= uint64(len(this.bits)) {
        return false
    }
    bitPos := num % bitSize
    // 右移 bitPos 位 和 1 进行 按位与
    return !(this.bits[byteIndex]&bitmask[bitPos] == 0)
}

func (this *bitmap) offset(num uint64) (byteIndex uint64, bitPos byte) {
    byteIndex = num / bitSize // 字节索引
    if byteIndex >= uint64(len(this.bits)) {
        panic(fmt.Sprintf(" runtime error: index value %d out of range", byteIndex))
        return
    }
    bitPos = byte(num % bitSize) // bit位置
    return byteIndex, bitPos
}

// 位图的容量
func (this *bitmap) Size() uint64 {
    return uint64(len(this.bits) * bitSize)
}

// 是否空位图
func (this *bitmap) IsEmpty() bool {
    return this.bitCount == 0
}

// 是否已填满
func (this *bitmap) IsFully() bool {
    return this.bitCount == this.capacity
}

// 已填入的数字个数
func (this *bitmap) Count() uint64 {
    return this.bitCount
}

// 获取填入的数字切片
func (this *bitmap) GetData() []uint64 {
    var data []uint64
    count := this.Size()
    for index := uint64(0); index < count; index++ {
        if this.Test(index) {
            data = append(data, index)
        }
    }
    return data
}

func (this *bitmap) String() string {
    var sb strings.Builder
    for index := len(this.bits) - 1; index >= 0; index-- {
        sb.WriteString(byteToBinaryString(this.bits[index]))
        sb.WriteString(" ")
    }
    return sb.String()
}

func byteToBinaryString(data byte) string {
    var sb strings.Builder
    for index := 0; index < bitSize; index++ {
        if (bitmask[7-index] & data) == 0 {
            sb.WriteString("0")
        } else {
            sb.WriteString("1")
        }
    }
    return sb.String()
}

代码中有注释,很容易看懂。下面写测试代码,测试这个bitmap。

package main

import (
    "bitmap"
    "fmt"
)

func main() {
    array := [...]uint64{0, 6, 3, 7, 2, 8, 1, 4}

    var maxNum uint64 = 9
    bm := bitmap.NewBitmap(maxNum)

    for _, v := range array {
        bm.Set(v)
    }
    bm.Set(5)
    fmt.Println(bm.IsFully())
    fmt.Println(bm.IsEmpty())
    fmt.Println("bitmap 中存在的数字:")
    fmt.Println(bm.GetData())
    fmt.Println("bitmap 中的二进制串")
    fmt.Println(bm.String())
    fmt.Println("bitmap 中的数字个数:", bm.Count())
    fmt.Println("bitmap size:", bm.Size())
    fmt.Println("Test(0):", bm.Test(0))
    bm.Reset(5)
    fmt.Println(bm.String())
    fmt.Println("Test(5):", bm.Test(5))
    fmt.Println(bm.GetData())
}

测试代码的输出如下:

true
false
bitmap 中存在的数字:
[0 1 2 3 4 5 6 7 8]
bitmap 中的二进制串
00000001 11111111
bitmap 中的数字个数: 9
bitmap size: 16
Test(0): true
00000001 11011111
Test(5): false
[0 1 2 3 4 6 7 8]

最后小结,bitmap的实现代码可以根据需要添加其它方法,本文的实现仅供参考。另外文中的代码不是线程安全的,多线程中使用需要改写bitmap的代码加上锁。

原文地址:https://www.cnblogs.com/aiandbigdata/p/11432310.html

时间: 2024-10-01 22:10:15

Go语言实现bitmap算法的相关文章

c语言递推算法1

递推算法之一:倒推法 1.一般分析思路: if 求解初始条件F1 then begin { 倒推 } 由题意(或递推关系)确定最终结果Fn; 求出倒推关系式Fi-1 =G(Fi ); i=n; { 从最终结果Fn出发进行倒推 } while 当前结果Fi非初始值F1 do 由Fi-1=G(Fi)倒推前项; 输出倒推结果F1和倒推过程; end { of then } else begin { 顺推 } 由题意(或递推关系)确定初始值F1(边界条件); 求出顺推关系式Fi=G(Fi-1); i=1

C语言值基本算法43—总结

C程序的基本算法共涵盖42个例题,包含了枚举.排列.逻辑判断.迭代.递推.字符串操作.矩阵操作.格式输出等内容. 相关的实现方法有的显得很笨拙,但足够说明问题,而且每个程序都经过作者亲测,保证可以运行.之所以称之为基本算法,就是为了测试基础知识的掌握,都是从原始的角度进行处理,没有运用过于花哨的处理技巧,作者也是在学习中进步,也希望这些代码对于没有基础或者基础薄弱的朋友带来帮助. 至此,基本知识就掌握了,我们常常会听说C的强大,因为它是面向过程的,在数学领域具有极好的应用,有必要进行进一步的学习

C语言实现FIFO算法与LRU算法

在操作系统中,当程序在运行过程中,若其所要访问的页面不再内存中而需要把他们调入内存,但内存已无空闲空间时,为了保证该进程能正常运行,系统必须从内存调出一页程序或数据送磁盘的兑换区中.但哪一个页面调出,须根据一定的算法确定.通常,把选择换出页面的算法称为页面置换算法(Page-Replacement Algorithms).置换算法的好坏将直接影响到系统的性能. 1) 先进先出(FIFO)页面置换算法 该算法总是淘汰最先进入内存的页面,即选择在内存中驻留时间最久的页面予以淘汰.该算法实现简单,只需

Bitmap算法应用

防火墙控制了某一目标IP的那些端口可以被用户IP访问,然而防火墙并没有用一条规则直接限定某一用户IP所能访问的目标IP及其端口,而是在配置中设置了一组访问控制规则,这些规则中既有允许访问的目标IP及端口范围,又有不允许访问的目标IP及端口范围.就某一目标IP而言,如何才能确定用户IP能访问该目标IP的端口呢?解决方案其实很简单,下面来看看具体步骤: 1.对于某一IP,假定0到65535之间的每一个端口都不允许访问,即可以创建一个大小为65536的Array数组,初始时每一个数组元素置为0,表示防

大数据处理算法一:Bitmap算法

腾讯面试题:给20亿个不重复的unsigned int的整数,没排过序的,然后再给一个数,如何快速判断这个数是否在那40亿个数当中并且所耗内存尽可能的少? 解析:bitmap算法就好办多了 所谓bitmap,就是用每一位来存放某种状态,适用于大规模数据,但数据状态又不是很多的情况.通常是用来判断某个数据存不存在的. 例如,要判断一千万个人的状态,每个人只有两种状态:男人,女人,可以用0,1表示.那么就可以开一个int数组,一个int有32个位,就可以表示32个人.操作的时候可以使用位操作. 一,

bitmap算法简介

今天看到海量数据处理算法----bitmap(又称为bitset, 或者bit array), 有意思的算法. C++ 有一个头文件是<bitset>. bitmap的思想就是数据压缩. 用一个二进制bit(0或者1)去标记某个元素对应的value, 这就是bit + map啊. 由于使用bit单位存储数据, 所以可大大节省内存空间.下面举一个使用bitmap 的例子. 我们要对0-7内的五个元素进行排序, 假设这5个元素为(4, 7, 2, 5, 3). 假设元素没有重复的. 要表示8个数,

经典算法题每日演练——第十一题 Bitmap算法

原文:经典算法题每日演练--第十一题 Bitmap算法 在所有具有性能优化的数据结构中,我想大家使用最多的就是hash表,是的,在具有定位查找上具有O(1)的常量时间,多么的简洁优美, 但是在特定的场合下: ①:对10亿个不重复的整数进行排序. ②:找出10亿个数字中重复的数字. 当然我只有普通的服务器,就算2G的内存吧,在这种场景下,我们该如何更好的挑选数据结构和算法呢? 一:问题分析 这年头,大牛们写的排序算法也就那么几个,首先我们算下放在内存中要多少G: (10亿 * 32)/(1024*

BitMap算法详解

所谓的BitMap就是用一个bit位来标记某个元素所对应的value,而key即是该元素,由于BitMap使用了bit位来存储数据,因此可以大大节省存储空间. 基本思想: 这此我用一个简单的例子来详细介绍BitMap算法的原理.假设我们要对0-7内的5个元素(4,7,2,5,3)进行排序(这里假设元素没有重复).我们可以使用BitMap算法达到排序目的.要表示8个数,我们需要8个byte. 1.首先我们开辟一个字节(8byte)的空间,将这些空间的所有的byte位都设置为0 2.然后便利这5个元

0.数据结构(python语言) 基本概念 算法的代价及度量!!!

先看思维导图: *思维导图有点简陋,本着循循渐进的思想,这小节的知识大多只做了解即可. *重点在于算法的代价及度量!!!查找资料务必弄清楚. 零.四个基本概念 问题:一个具体的需求 问题实例:针对问题(需求)的具体的例子 算法:解决问题的过程,是对一个计算过程的严格描述 程序:程序可以看作是采用计算装置能够处理的语言描述的算法 一.算法的5大性质 有穷性(算法描述的又穷性):算法必须用有限长的描述说清楚 能行性:算法的每一步都是可行的,也就是说,每一步都能通过执行有限次数完成 确定性:别人看了过