golang实现的bitmap,增减查元素,附单元测试

yanglikai · · 696 次点击 · · 开始浏览    
这是一个创建于 的文章,其中的信息可能已经有所发展或是发生改变。

bitmap.go

package ...

import (
	"bytes"
	"fmt"
)

type Bitmap struct {
	//按64*i取模后得到的值(i为数组元素下标)
	modValues  []uint64
	length int
}

func (bitmap *Bitmap) IsExist(num int) bool {
	floor, bit := num/64, uint(num%64)
	return floor < len(bitmap.modValues) && (bitmap.modValues[floor]&(1<<bit)) != 0
}

//加入一个数,返回值:是否操作成功,true:本身不存在,加入成功;false:本身已存在
func (bitmap *Bitmap) Add(num int) bool {
	floor, bit := num/64, uint(num%64)
	isExist := false
	for floor >= len(bitmap.modValues) {
		bitmap.modValues = append(bitmap.modValues, 0)
		isExist = true
	}
	//余数转成对应bit位的值
	remainder := uint64(1<<bit)
	// 判断num是否已经存在bitmap中
	if !isExist && bitmap.modValues[floor] & remainder != 0 {
		return false
	}

	isExist = true
	//余数对应的bit位值置为1
	bitmap.modValues[floor] |= remainder
	bitmap.length++
	return isExist
}

//去掉一个数,返回值:是否操作成功,true:本身存在,被删除;false:本身就不存在
func (bitmap *Bitmap) Sub(num int) bool {
	floor, bit := num/64, uint(num%64)
	for floor >= len(bitmap.modValues) {
		return false
	}
	// 判断num是否已经存在bitmap中,不存在直接返回false
	if bitmap.modValues[floor] & (1<<bit) == 0 {
		return false
	}
	//余数对应的bit位值置为0
	bitmap.modValues[floor] -= 1 << bit
	bitmap.length--
	return true
}

func (bitmap *Bitmap) Len() int {
	return bitmap.length
}

func (bitmap *Bitmap) String() string {
	var buf bytes.Buffer
	buf.WriteByte('{')
	for i, v := range bitmap.modValues {
		if v == 0 {
			continue
		}
		uinti := uint(i)
		for j := uint(0); j < 64; j++ {
			if v & (1<<j) != 0 {
				if buf.Len() > 1 {
					buf.WriteByte(',')
				}
				fmt.Fprintf(&buf, "%d", 64 * uinti + j)
			}
		}
	}
	buf.WriteByte('}')
	fmt.Fprintf(&buf,"\nLength: %d", bitmap.length)
	return buf.String()
}

单元测试(bitmap_test.go):

package ...

import (
	"fmt"
	. "github.com/smartystreets/goconvey/convey"
	"testing"
)

func Test_Bitmap(t *testing.T) {
	Convey("test Bitmap", t, func() {
		bitmap := new(Bitmap)

		So(bitmap.Add(3), ShouldBeTrue)
		So(len(bitmap.modValues) == 1, ShouldBeTrue)
		//fmt.Println(bitmap.String())
		
		So(bitmap.length == 1, ShouldBeTrue)
		So(bitmap.Add(5), ShouldBeTrue)
		So(len(bitmap.modValues) == 1, ShouldBeTrue)
		So(bitmap.length == 2, ShouldBeTrue)
		So(bitmap.Add(63), ShouldBeTrue)
		So(len(bitmap.modValues) == 1, ShouldBeTrue)
		So(bitmap.length == 3, ShouldBeTrue)
		So(bitmap.Add(64), ShouldBeTrue)
		So(len(bitmap.modValues) == 2, ShouldBeTrue)
		So(bitmap.Add(127), ShouldBeTrue)
		So(len(bitmap.modValues) == 2, ShouldBeTrue)
		So(bitmap.length == 5, ShouldBeTrue)
		So(bitmap.Add(128), ShouldBeTrue)
		So(len(bitmap.modValues) == 3, ShouldBeTrue)
		So(bitmap.Add(256), ShouldBeTrue)
		So(len(bitmap.modValues) == 256/64+1, ShouldBeTrue)
		So(bitmap.Add(511), ShouldBeTrue)
		So(len(bitmap.modValues) == 512/64, ShouldBeTrue)
		So(bitmap.length == 8, ShouldBeTrue)
		So(bitmap.Add(513), ShouldBeTrue)
		So(len(bitmap.modValues) == 512/64+1, ShouldBeTrue)
		So(bitmap.length == 9, ShouldBeTrue)

		//fmt.Println(bitmap.Add(63))
		fmt.Println(bitmap.String())

		So(bitmap.Add(63), ShouldBeFalse)
		So(len(bitmap.modValues) == 512/64+1, ShouldBeTrue)
		So(bitmap.length == 9, ShouldBeTrue)

		So(bitmap.Sub(632), ShouldBeFalse)
		So(len(bitmap.modValues) == 512/64+1, ShouldBeTrue)
		So(bitmap.length == 9, ShouldBeTrue)

		So(bitmap.Sub(63), ShouldBeTrue)
		So(len(bitmap.modValues) == 512/64+1, ShouldBeTrue)
		So(bitmap.length == 8, ShouldBeTrue)

		So(bitmap.Sub(513), ShouldBeTrue)
		So(len(bitmap.modValues) == 512/64+1, ShouldBeTrue)
		So(bitmap.length == 7, ShouldBeTrue)
	})
}

 


有疑问加站长微信联系(非本文作者)

入群交流(和以上内容无关):加入Go大咖交流群,或添加微信:liuxiaoyan-s 备注:入群;或加QQ群:692541889

696 次点击  
加入收藏 微博
添加一条新回复 (您需要 登录 后才能回复 没有账号 ?)
  • 请尽量让自己的回复能够对别人有帮助
  • 支持 Markdown 格式, **粗体**、~~删除线~~、`单行代码`
  • 支持 @ 本站用户;支持表情(输入 : 提示),见 Emoji cheat sheet
  • 图片支持拖拽、截图粘贴等方式上传