海量数据处理:BitMap

版权声明:本博客为记录本人学习过程而开,内容大多从网上学习与整理所得,若侵权请告知! https://blog.csdn.net/Fly_as_tadpole/article/details/88879668

利用Java里的BitSet位集合实现:

有四十亿个扣扣号,拿来一个扣扣号,最快速查找?

一、问题描述:

  1.在42亿个qq号码中,如何使用O(1)时间复杂度去查找一个QQ号是否存在。

  2.qq号的位数小于13位,存储着42亿QQ号的内存不得超过600MB.

二、位图排序思想

  由于待排序的数据记录较多,我们单纯地使用常见的排序方法时间效率较低,运行时间会很长。而且内存空间有限(限制为1MB左右),所以我们不能同时把所有整数读入内存(如果每个整数使用7个字节来存储,那么1MB内存空间只能存大约143000个数字)。当然我们可以多次读取输入文件,多次排序,但是更好的方案是使用位图排序,可以使用有限的1MB内存空间并只进行一趟排序。

      1.根据待排序集合中最大的数,开辟一个位数组,用来表示待排序集合中的整数;//这里可能被问大数据TOPK

      2.待排序集合中的数字在位数组中的对应位置置1,其他的置0;

      例如,待排序集合{1,2,3,5,8,13}可以表示为:0-1-1-1-0-1-0-0-1-0-0-0-0-1

      这样排序过程自然可以分为三步:

      第一步:将所有的位都置为0;

      第二步:通过读入文件中的每个整数,将每个对应的位都置为1;

      第三步:检验每一位,如果该位为1,输出对应的整数。

      注意:位图排序是使用一个二进制位而不是一个整数来表示0或1,这样可以大大地减少所需要的内存空间。使用位图排序的前提是要知道待排序序列中的最大数。位图排序的缺点是有些数没有出现过,仍要为其保留一个位。故位图排序比较适合关键字密集的序列,例如一个QQ号码。

/*Phase 1: initialize set to empty*/
 
  for
i = [0, n)
 
    bit[i] = 0
 
/*Phase 2: insert present elements into the set*/
 
  for
each i in the input file
 
    bit[i] = 1
 
/*Phase 3: write sorted output*/
 
  for
i = [0, n)
 
    if
bit[i] == 1
 
      write i on the output file
三、使用位图排序的方法

      位图排序时,我们需要考虑:给出一个数,如何找到其对应位图的位置,方法就是首先找到该数对应的字节,然后在找到该数对应的位。例如一个QQ号是:983262245,则将bit的98326625位进行标记。bitset是C++提供的一种位集合的数据结构,它让我们可以像使用数组一样使用位,可以访问指定下标的bit位。因此将通过bitset容器进行存储42个qq号码。由于一个字节可以存放8个QQ号码,则4200000000/8/1014/1024 = 500.679Mb,内存合适,通过bit位下表来判断QQ号码是否存在。

#include<iostream>
#include<bitset>
#include<cstdio>
#include<vector>
#include<algorithm>
using namespace std;
const unsigned int MAX = 4200000010;
typedef unsigned int UT;
bitset<MAX> bit;
int main(){
    //开始存储QQ
    for(UT i=1;i<10;i++){
        UT qq;
        printf("请输入第%d个QQ号:",i);
        scanf("%d",&qq); 
        bit.set(qq);
    } 
    UT qq;
    printf("请输入:");
    while(scanf("%d",&qq)!=0){
            
        if(bit.test(qq)){
            printf("Yes\n");
        }
        printf("请输入:");
    }
    return 0;

存储:空间占用大约500Mb

查找:时间复杂度为O(1)

通过位排序的方法,在实现内存内,实现在O(1)时间复杂度内进行一个QQ号码的查找。
 


package bitmap;

import java.math.BigInteger;
import java.util.BitSet;
import java.util.Scanner;

public class BitMap {

    private static final  int MAX = 420000010;

    public static void main(String[] args) {
        BitSet bitSet = new BitSet(MAX);
        int[] qq = {
                111111111,
                222222222,
                333333333,
                444444444,
                555555555
        };
        for(int i = 0;i<qq.length;i++){
            bitSet.set(qq[i]);
        }

        Scanner scanner = new Scanner(System.in);
        while(scanner.hasNext()){
            int num = scanner.nextInt();
            if(bitSet.get(num)){
                System.out.println("在");
            }else{
                System.out.println("不在");
            }

        }
    }

}

猜你喜欢

转载自blog.csdn.net/Fly_as_tadpole/article/details/88879668