C++哈希的应用--位图+哈希的一些补充

本文介绍了如何使用位图和哈希算法解决大数据量整数判断问题。针对给定的40亿无重复整数,通过位图策略,仅需500MB内存就能快速判断一个数是否存在。位图的实现包括通过char或int数组存储,以及如何设置、检查和清除比特位。此外,文章还讨论了哈希表的扩容策略,提出在扩容时选择素数大小以优化哈希性能。
摘要由CSDN通过智能技术生成

目录

位图

位图的实现

将x对应比特位0置1

将x对应比特位1置0

查看x位置是0还是1

位图的应用

哈希的补充


首先我们来看一道题,这是一道笔试题。

给40亿个不重复的无符号整数,没排过序。给一个无符号整数,如何快速判断一个数是否在这40亿个数 中。

1. 遍历,时间复杂度O(N)

2. 排序(O(NlogN)),利用二分查找: logN

        当用二分查找,比如AVL树,最多要查找高度次。所以log40亿=32,最多要查找32次.它们都很快,但是这里有一个大麻烦,1G=1024*1024*1024byte,那么1G大概是10亿字节,一个整数要4个字节,那么10亿个整数大约要4G,所以40亿个整数要占16G的空间。16G在内存中已经块存不下了。

        并且哈希表和红黑树这种还有附带消耗,比如红黑树的节点中不仅要存key值,还要存三叉链:左孩子、右孩子、父亲指针和颜色,这样就16个字节了(指针都是4个字节在32位下,颜色用的是枚举,也是4个字节)。用哈希表的话,每个节点还要存next指针,也要消耗4个字节。并且还有一个表的消耗,消耗也不小。

3.位图

        数据是否在给定的整形数据中,结果是在或者不在,刚好是两种状态,我只需要判断在还是不在即可。那么可以使用一个二进制比 特位来代表数据是否存在的信息,如果二进制比特位为1,代表存在,为0代表不存在。

位图

那么如果40亿个值存不下了,就会在磁盘文件当中存储。

40亿个整数,每个值一个比特位,那么就是40亿个比特位,要占0.5G也就是500M。刚才我们已经直到40亿个整数要存16G,一个整数是4字节,一个字节8byte,那么一个整数是32byte,16G/32byte=0.5G=500M。500M对于内存是可以承受的。

但是40亿个整数不能只开40亿个比特位,需要按照整数的范围42亿来开,接近43亿。32位下,一个整数是4字节,4字节是32byte,那么整数的范围大小有2^32,一共42亿个。那么在这个40亿个整数中,有可能存在41亿的数,也有可能存在42亿的数。所以位图开比特位需要按照整数范来开,需要开42亿个比特位。

位图的实现

在C++中我们无法开辟比特位,但是我们可以开数组,开一个char类型的数组,每个数组元素类型是char,一个char是1字节=8byte,如果要开N个字节,那么就要开N/8个char类型的数组。或者也可以开int类型数组,这样每个数组元素存放的元素比特位更大,一个int=4字节=32byte,那么要开辟N个比特位,就要开辟N/32个int类型数组。

所以位图的私有成员变量可以是vector<char> _bits;也可以是vector<int> _bits;我们这里存char来举例。

如果按char存,不管它大端还是小端,它的第一个vector存的是0-7个比特位,第二个vector寸的是8-15个比特位,以此类推。如果是int类型的第一个vector存的是0-31个比特位,一个vector存32byte。

最开始我们要构造初始化这个vector,需要resize开辟空间,在上面我们提到给数组开辟空间,要开N/8个大小的char类型数组。但是这样的话,如果遇到不是8倍数的N,加入N是10,10/8之后结果转

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值