学习Bitmap,处理“海量”数据

我在前面的随笔里已经写过关于处理海量数据的哈希表和Trie的方法了,本文提到的是常用方法之一:Bitmap,测试数据是100万条随机数。

Bitmap是用于处理有限位数的整数,理论上,对于1GB的内存,处理的整数范围大约在0-8,000,000,000内,即一般处理10亿以内,同时也是10位数以内的数据,可实现的操作有存储,排序,查找,删除,查重

而朴素的方法处理10亿的整数需要40GB以上的内存空间,所以,在int用32位表示的机器上,理论内存空间使用比例为1:32,我在下面的代码里用到的测试数据是100万条1亿以内的随机数,完成增删查排序功能。

欢迎有共同学习兴趣的同学加好友探讨学习哦~~^_^

代码:

  1 #include <stdlib.h>
  2 #include <string.h>
  3 #include <time.h>
  4 #include <fstream>
  5 #include <sys/timeb.h>
  6 #include <basetsd.h>
  7 /**
  8 * @author:zanzan101
  9 */
 10 using namespace std;
 11 
 12 unsigned int* build_bitmap(const unsigned int m)
 13 {
 14     // 建立一个空bitmap
 15     // 我这里是用1位表示一条记录,没有查重的功能,如果用2位表示,或者使用双bitmap,则可以实现查重
 16     unsigned int* p = new unsigned int[1 + m/(8*sizeof(unsigned int))];
 17     memset(p, 0, m/8 + sizeof(unsigned int));
 18     return p;
 19 }
 20 
 21 void set_bit(unsigned int* arr, unsigned int n)
 22 {
 23     // 常数时间插入任何一个数
 24     unsigned int pos = n/(8*sizeof(unsigned int));
 25     unsigned int tmp = n%(8*sizeof(unsigned int));
 26     unsigned int msk = (unsigned int)1 << tmp;
 27     arr[pos] |= msk;
 28 }
 29 unsigned int get_bit(unsigned int* arr, unsigned int n)
 30 {
 31     // 常数时间查找任何一个数
 32     unsigned int pos = n/(8*sizeof(unsigned int));
 33     unsigned int tmp = n%(8*sizeof(unsigned int));
 34     unsigned int msk = (unsigned int)1 << tmp;
 35     tmp = arr[pos];
 36     tmp &= msk;
 37     return tmp>0?1:0;
 38 }
 39 void delete_bit(unsigned int* arr, unsigned int n)
 40 {
 41     // 常数时间删除任何一个数
 42     unsigned int pos = n/(8*sizeof(unsigned int));
 43     unsigned int tmp = n%(8*sizeof(unsigned int));
 44     unsigned int msk = (unsigned int)1 << tmp;
 45     msk = ~msk;
 46     arr[pos] &= msk;
 47 }
 48 
 49 
 50 void save_bitmap(unsigned int* arr, unsigned int m)
 51 {
 52     ofstream output_file;
 53     output_file.open("D:\test_bitmap___.txt");
 54     if(!output_file.is_open())
 55         return;
 56 
 57     // bitmap 本身就是有序的,只需从前往后依次遍历访问即可有序输出
 58     for(unsigned int i = 0; i < m; i++)
 59         if(get_bit(arr, i))
 60             output_file << i << endl;
 61 }
 62 
 63 void print_bitmap(unsigned int* arr, unsigned int m)
 64 {
 65     if(m > 100)
 66     {
 67         printf("数据量过大,不便于在屏幕上显示,已存入文件:D:\test_bitmap___.txt
");
 68         save_bitmap(arr, m);
 69         return;                //数据量过大时,还是保存到文件里比较好~~~
 70     }
 71 
 72     // bitmap 本身就是有序的,只需从前往后依次遍历访问即可有序输出
 73     for(int i = 0; i < m; i++)
 74         if(get_bit(arr, i))
 75             printf("%8d ", i);
 76     printf("
");
 77 }
 78 
 79 unsigned int big_rand(const unsigned int max)
 80 {
 81     unsigned int sum = 0;
 82     int tmp = max/RAND_MAX;
 83     if(!tmp)
 84         return rand()%max;
 85 
 86     int round = rand()%tmp;
 87     sum += RAND_MAX*round;
 88     sum += rand();
 89     return sum;
 90 }
 91 
 92 int main()
 93 {
 94     timeb time_begin;
 95     timeb time_end;
 96     unsigned int seconds;
 97     unsigned int miseconds;
 98 
 99     const unsigned int MAX = 100000000;
100     unsigned int* bitmap = build_bitmap(MAX);
101     srand(time(0));
102     // 测试插入功能
103     // 插入100万条随机数
104     printf(">> 插入:100万条%u以内的随机数
", MAX);
105     for(int i = 0; i < 1000000; i++)
106         set_bit(bitmap, big_rand(MAX));
107 
108     // 测试排序功能
109     // bitmap本身就是有序的
110     printf(">> 排序:
");
111     print_bitmap(bitmap, MAX);
112 
113     // 测试查找功能
114     printf(">> 查找:100个%u以内的随机数
由于是随机数,其实找到每个数的概率是0.01,下面只显示找到的情况
", MAX);
115     ftime(&time_begin);    
116     int ran;
117     for(int i = 0; i < 100; i++)
118     {
119         ran = big_rand(MAX);
120         if(get_bit(bitmap, ran))
121             printf("	%d存在!
", ran);
122 //        由于找到的概率比较小,下面就不显示没有找到的情况了
123 //        else                                
124 //            printf("	%d不存在!
", ran);
125     }
126     ftime(&time_end);
127     seconds = time_end.time - time_begin.time;
128     miseconds = time_end.millitm - time_begin.millitm;
129     miseconds = seconds * 1000 + miseconds;
130     printf(">> 100次查找总共耗时:%u毫秒
", miseconds);
131 
132     // 现插入现找
133     ran = big_rand(MAX);
134     set_bit(bitmap, ran);
135     printf(">> 查找:现插入随机数%d,再查找它
", ran);
136 
137     if(get_bit(bitmap, ran))
138         printf("	%d存在!
", ran);
139     else
140         printf("	%d不存在!
", ran);
141 
142     // 测试删除功能
143     // 删除刚才插入的那个随机数
144 
145     printf(">> 删除:刚才插入的那个随机数%d删掉,之后再查找它
", ran);
146     delete_bit(bitmap, ran);
147     if(get_bit(bitmap, ran))
148         printf("	%d存在!
", ran);
149     else
150         printf("	%d不存在!
", ran);
151     delete[] bitmap;
152     system("pause");
153     return 0;
154 }

输出结果:

>> 插入:100万条100000000以内的随机数
>> 排序:
数据量过大,不便于在屏幕上显示,已存入文件:D:	est_bitmap___.txt
>> 查找:100个100000000以内的随机数
由于是随机数,其实找到每个数的概率是0.01,下面只显示找到的情况
        92857475存在!
        19411480存在!
        58457743存在!
        37785850存在!
        26831485存在!
>> 100次查找总共耗时:0毫秒
>> 查找:现插入随机数82440561,再查找它
        82440561存在!
>> 删除:刚才插入的那个随机数82440561删掉,之后再查找它
        82440561不存在!
请按任意键继续. . .
原文地址:https://www.cnblogs.com/zanzan101/p/3348649.html