位示图用法的总结

今天在复习的过程中,遇到了海量数据处理问题,这种问题是一种常见的TOP K 问题,处理方法比较固定就是考虑两种情况,一种情况是内存中能够将数据全部存储下来,另一种情况是不能将数据全部存储下来。对于第一种情况,直接采用hash_map进行统计,然后通过堆排序进行建立一个K大小的堆,然后将数据存储到堆里,最终获取Top K。

另一种情况的解决方式是先hash分治,然后对每份进行hash_map统计,然后可以采用归并排序或者堆排序来进行最后将每个的TOP K 问题合并在进行排序就可以获取最终的topK答案。

今天我想总结的不是海亮数据处理,而是位示图在上亿数据中的处理方式,先从一个腾讯的面试题开始:

给定40亿个整数,没有排过序,在给定一个整数,问如何快速的判断这个数是否在这些数中?

方法一:
使用位示图法,因为40个整数,最多需要40亿个bit位就可以表示,所以512MB内存就可以存储这些数字,然后逐个读取这40亿个数字,然后将相应的位置1,最后查看这个数所对应的bit
是否为1,如果是1,则说明这40亿个数字中存在这个数,否则不存在。
方法二:
因为每个unsigned int整数都是32位的,而且每个位要么是 1 要么是 0 ,所以先根据最高位是0还是1将数据分成两份,然后看要查找的数字最高位,选择对应的一份,然后
再根据次高位,将数据再分成两份,而且查看要查找的数字的次高位,选择一份,如此最多需要进行32次查找就可以确定,这个数是否存在。但是IO会比较多。
方法三:
如果这40亿个数的重复率很高的话,或者说在一个范围之内,则可以选择桶排序进行排序,然后在对应的桶里进行查找。

第一种方法就显示了位示图的用法。以下就总结一下位示图在算法中的应用:
1、采用位示图法对数据进行排序
首先确定一组数中的最大值和最小值,然后构造位数组,读取这些数并将对应的位置一。最后输出每个bit对应的数字就可以了。

2、采用位示图判断数组中是否有重复的数字
根据最大值,构造一个位数组,然后逐个读取数字,将对应的bit置一,然后在后面的逐个读取中,若所对应的bit=1,则可以知道这些数字中存在重复的数字。

3、采用位示图存储数据
如果要求用8K的空前存储unsigned short数据的话,普通做法如下:

unsigned short usarray[4096],因为每个unsinged int占有两个字节的空间,所以会一共存储4K个数据。

如果采用以下方法则可以存储更多的数据:

unsigned char ucarray[8192],因为每个unsigned char占有一个字节的空间,同时每个字节8个bit,可以存储8个数字,所以会一共可以存储 8K*8 = 64K个数字

存储方法如下:先确定这个数组中对应的下标,index,然后在内部获取第几个位(如x)这样就可以采用 index*8+x表示一个数字
如果要存储 1234,则通过 1234/8 = 154,知道存储在ucarray[154],然后通过 1234 - 154*8 = 2,可以知道用第二个bit来存储这个数字就可以了。

以上简单介绍了位示图的几个用法,当然位示图也有自己的缺陷:
1、表示不直观,可读性差。
2、虽然位示图可以比一般的存储多存储很多,但是它受限与内存的大小。比如说例题中的第二种方法,虽然IO量增大了,但是可以处理更多的数据,而如果给予的内存只有128MB那么就
不能存储这40亿个整数。
3、当表示带符号的数字的时候,需要拿出2位表示符号,这个时候能够存储的数据量就会成倍的减少。

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值