位图算法—Golang的简单实现

位图算法以及golang的简单实现。

一、位图算法介绍

位图(bitmap)算法原理:采用bit位来存储数据并建立相应映射关系。

位图(bitmap)算法优点:大大减少了存储空间,也加快了大量数据查询的时间。

位图(bitmap)算法缺点:当位图(bitmap)中存储的数据较少时,存入比较大的数值,会占用比较大的内存空间。

二、位图算法应用场景

位图算法应用场景如下:

1)单状态筛选,比如用户是否在线或者离线,可以根据用户数据库id当作查询数值,查询相应的位数。相应位数为1,即代表用户在线;相应位数为0,用户不在线。

2)多状态筛选,比如大量用户客户端,需要选择区域性的服务器服务,这时可以给服务器编号,根据服务器数量选择占用的位数来代表单个用户的服务器id,如果有4台服务器,就用两位来表示单个用户的服务器编号。

3)内存不足,大量确定范围的数值排序。

4)大量数据去重压缩,比如爬虫爬到的url去重。

三、Golang的简单实现

以下代码实现了1~2^63数值存储映射,输出是小端顺序,未补全0占位。

注:golang在64位机器中运行,int占用8byte,在32位机器中运行,int占用4byte。

type BitMap struct {
	bitmap []byte
	length int
}

func NewBitMap() *BitMap {
	return &BitMap{}
}

func (bitmap *BitMap) Add(num int) {
	if num == 0 {
		return
	}
	byteIndex := num / 8
	offsetIndex := num % 8
	if byteIndex+1 >= bitmap.length {
		if offsetIndex > 0 {
			bitmap.bitmap = append(bitmap.bitmap, make([]byte, byteIndex-len(bitmap.bitmap)+1)...)
		} else {
			bitmap.bitmap = append(bitmap.bitmap, make([]byte, byteIndex-len(bitmap.bitmap))...)
		}
	}
	if offsetIndex == 0 {
		if byteIndex >= 1 {
			bitmap.bitmap[byteIndex-1] |= 1
		}
	} else {
		bitmap.bitmap[byteIndex] |= 1 << (8 - offsetIndex)
	}
	bitmap.length = len(bitmap.bitmap)
}

func (bitmap *BitMap) Del(num int) {
	byteIndex := num / 8
	offsetIndex := num % 8
	if bitmap.Exist(num) {
		if offsetIndex == 0 {
			if byteIndex >= 1 {
				if (bitmap.bitmap[byteIndex-1] & 1) != 0 {
					bitmap.bitmap[byteIndex-1] &= ^uint8(1)
				}
			}
			return
		}
		if bitmap.bitmap[byteIndex]&(1<<(8-offsetIndex)) != 0 {
			bitmap.bitmap[byteIndex] &= ^uint8(1 << (8 - offsetIndex))
		}
	}
	return
}

func (bitmap *BitMap) Exist(num int) bool {
	if num == 0 {
		return false
	}
	byteIndex := num / 8
	offsetIndex := num % 8
	if (byteIndex > bitmap.length) || (byteIndex == bitmap.length && offsetIndex > 0) {
		return false
	}
	if offsetIndex == 0 {
		if byteIndex >= 1 {
			return bitmap.bitmap[byteIndex-1]&1 != 0
		}
	}
	return bitmap.bitmap[byteIndex]&(1<<(8-offsetIndex)) != 0
}

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

func (bitmap *BitMap) ToString() string {
	return fmt.Sprintf("%b", bitmap.bitmap)
}

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值