Go实现bitmap算法

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

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

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

42

43

44

45

46

47

48

49

50

51

52

53

54

55

56

57

58

59

60

61

62

63

64

65

66

67

68

69

70

71

72

73

74

75

76

77

78

79

80

81

82

83

84

85

86

87

88

89

90

91

92

93

94

95

96

97

98

99

100

101

102

103

104

105

106

107

108

109

110

111

112

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。

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

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的代码加上锁。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值