位图法定义

位图法就是bitmap的缩写,所谓bitmap,是用每一位来存放某种状态,适用于大规模数据,但数据状态又不是很多的情况。通常是用来判断某个数据存不存在的。

例如,要判断一千万个人的状态,每个人只有两种状态:男人,女人,可以用0,1表示。那么就可以开一个int数组,一个int有32个位,就可以表示32个人。操作的时候可以使用位操作。
 
本文地址:http://www.cnblogs.com/archimedes/p/bitmap.html,转载请注明源地址。

数据结构

unsigned int bit[N];
在这个数组里面,可以存储 N * sizeof(int) * 8个数据,但是最大的数只能是N * sizeof(int)  * 8 - 1。假如,我们要存储的数据范围为0-15,则我们只需要使得N=1,这样就可以把数据存进去。如下图:
数据为【5,1,7,15,0,4,6,10】,则存入这个结构中的情况为

位图法应用

一、给40亿个不重复的unsigned int的整数,没排过序的,然后再给一个数,如何快速判断这个数是否在那40亿个数当中

申请512M的内存

一个bit位代表一个unsigned int值

读入40亿个数,设置相应的bit位

读入要查询的数,查看相应bit位是否为1,为1表示存在,为0表示不存在

二、使用位图法判断整形数组是否存在重复

判断集合中存在重复是常见编程任务之一,当集合中数据量比较大时我们通常希望少进行几次扫描,这时双重循环法就不可取了。位图法比较适合于这种情况,它的做法是按照集合中最大元素max创建一个长度为max+1的新数组,然后再次扫描原数组,遇到几就给新数组的第几位置上1,如遇到 5就给新数组的第六个元素置1,这样下次再遇到5想置位时发现新数组的第六个元素已经是1了,这说明这次的数据肯定和以前的数据存在着重复。这种给新数组初始化时置零其后置一的做法类似于位图的处理方法故称位图法。它的运算次数最坏的情况为2N。如果已知数组的最大值即能事先给新数组定长的话效率还能提高一倍。

#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include<stdbool.h> bool hasDuplicatedItem(int *a, int len)
{
int length, max, i;
length = len;
max = a[0];
for(i = 1; i < length; i++){
if(a[i] > max)
max = a[i];
}
int *arr;
arr = (int*)malloc(sizeof(int) * (max + 1));
for(i = 0; i < length; i++){
if(arr[a[i]])
return true;
else
arr[a[i]] = 1;
}
return false;
} int main()
{
int length;
int test[] = {0,1,2,3,45,12,13};
length = (sizeof(test) / sizeof(test[0]));
if(hasDuplicatedItem(test, length))
printf("hasDuplicatedItem!\n");
else
printf("hasNoDuplicatedItem!\n");
return 0;
}

三、使用位图法进行整形数组排序

首先遍历数组,得到数组的最大最小值,然后根据这个最大最小值来缩小bitmap的范围。这里需要注意对于int的负数,都要转化为unsigned int来处理,而且取位的时候,数字要减去最小值。

#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include<stdbool.h> void bitmapSort(int *a, int len)
{
int length, max, min, i, index;
length = len;
min = max = a[0];
//找出数组最大值
for(i = 1; i < length; i++){
if(a[i] > max){
max = a[i];
}
if(min > a[i]) {
min = a[i];
}
}
//得到位图数组
int *arr;
arr = (int*)malloc(sizeof(int) * (max - min + 1));
for(i = 0; i < length; i++){
index = a[i] - min;
arr[index]++;
}
//重整a中的元素
int arr_length;
arr_length = max - min + 1;
index = 0;
for(i = 0; i < arr_length; i++){
while(arr[i] > 0){
a[index] = i + min;
index++;
arr[i]--;
}
}
} void print(int *a, int n)
{
int i;
for(i = 0; i < n; i++) {
printf("%d ", a[i]);
}
printf("\n");
} int main()
{
int length;
int test[] = {50,1,26,3,45,12,13};
length = sizeof(test) / sizeof(test[0]);
print(test, length);
bitmapSort(test, length);
print(test, length);
return 0;
}

四、位图法存数据

输入:一个最多包含n个正整数的文件,每个数都小于n,其中n=10,000,000 输入文件中没有重复的整数,没有其他数据与该整数相关联。

输出: 按升序排列这些数。

约束:有 1MB多(不超过2MB) 的内存空间可用,有充足的硬盘空间。

#include<stdio.h>
#define BITSPERWORD 32
#define SHIFT 5
#define MASK 0x1F
#define N 10000000
int a[1 + N/BITSPERWORD]; /* a[i>>SHIFT]是第i位应该在第几个int上 */
/* (1<<(i & MASK))是第i位在该int上的第几个bit */ void set(int i)
{
a[i>>SHIFT] |= (1<<(i & MASK));//关键!!!!!!!!!!!!!!!!!
} void clr(int i)
{
a[i>>SHIFT] &= ~(1<<(i & MASK));
} int test(int i)
{
return a[i>>SHIFT] & (1<<(i & MASK));
} int main()
{
int i;
for(i = 0; i < N; i++)
clr(i);
while(scanf("%d", &i) != EOF)
set(i);
for(i = 0; i < N; i++)
if(test(i))
printf("%d\n", i);
return 0;
}

bitmap位图法的更多相关文章

  1. 位图法bitmap

    1.概念 1)所谓bitmap,就是用每一位(bit)来标记某个元素对应的value, 而key即是该元素,通常bitmap是一个int数组,用每一个int数的每一个bit来映射某个数据 2)由于采用 ...

  2. BitMap位图与海量数据的理解

    1. Bit Map算法简介 来自于<编程珠玑>.所谓的Bit-map就是用一个bit位来标记某个元素对应的Value, 而Key即是该元素.由于采用了Bit为单位来存储数据,因此在存储空 ...

  3. BitMap位图与海量数据的理解与应用

    1. Bit Map算法简介 来自于<编程珠玑>.所谓的Bit-map就是用一个bit位来标记某个元素对应的Value, 而Key即是该元素.由于采用了Bit为单位来存储数据,因此在存储空 ...

  4. 大数据位图法(无重复排序,重复排序,去重复排序,数据压缩)之Java实现

    1,位图法介绍 位图的基本概念是用一个位(bit)来标记某个数据的存放状态,由于采用了位为单位来存放数据,所以节省了大量的空间.举个具体的例子,在Java中一般一个int数字要占用32位,如果能用一位 ...

  5. 05 redis中的Setbit位图法统计活跃用户

    一:场景=>>>长轮询Ajax,在线聊天时,能够用到 Setbit 的实际应用 场景: 1亿个用户, 每个用户 登陆/做任意操作 ,记为 今天活跃,否则记为不活跃 每周评出: 有奖活 ...

  6. BitMap位图

    BitMap位图算法https://blog.csdn.net/varyall/article/details/79662029 常见面试题 题1:在2.5亿个整数找出不重复的整数,内存不足以容纳着2 ...

  7. 重温delphi之:如何将Bitmap位图与base64字符串相互转换

    先引用delphi自带的单元 uses EncdDecd; 然后就可以使用下面二个函数了: by 菩提树下的杨过 http://yjmyzz.cnblogs.com/ ///将Bitmap位图转化为b ...

  8. delphi中Bitmap位图与base64字符串相互转换

    uses EncdDecd; ///将Bitmap位图转化为base64字符串 function BitmapToString(img:TBitmap):string ; var ms:TMemory ...

  9. bittorrent 学习(一) 种子文件分析与bitmap位图

    终于抽出时间来进行 BITTORRENT的学习了 BT想必大家都很熟悉了,是一种文件分发协议.每个下载者在下载的同时也在向其他下载者分享文件. 相对于FTP HTTP协议,BT并不是从某一个或者几个指 ...

随机推荐

  1. [Egret]长按截屏分享、分享截屏图片、本地存储

    egret 分享有API可以把一个显示对象树渲染成一个位图纹理,我把它赋值给 HTML 的 Image 元素,就实现了图片的显示,在微信中,通过长按图片可以分享出去.当然在其他浏览器可以保存在本地. ...

  2. 解决错误: ios property has a previous declaration

    今天维护一个项目的时候,我新添加了一个库,运行的时候报错了: ios property has a previous declaration 上网查了一下没有找到思路,不过根据提示自己试了一下,原来这 ...

  3. [转]Linux(Ubuntu)下如何安装JDK

    转自:http://www.cnblogs.com/savagemorgan/p/3650926.html 注:这篇博客里面有两个问题 1.解压的时候不用sudo,mv的时候不用sudo,我的安装路径 ...

  4. springboot2.0 fastjson 日期格式化不生效解决

    网上有很多介绍,主要有两种. 1.在启动类中注入bean /** * 集成fastjson * * @return */ @Bean public HttpMessageConverters fast ...

  5. JS——简单的正则表达式验证

    <!-- 用户注册:结构层:html;表现层:css;行为层:javascript; html利用ul,li来构造: 注意事项:1.每个Input都要有相应的id,这是在js中去调用的. 2.& ...

  6. U盘工作原理(转)

    u盘工作原理 一. U盘基本工作原理 通用串行总线(Universal serial Bus)是一种快速灵活的接口, 当一个USB设备插入主机时,由于USB设备硬件本身的原因,它会使USB总线的数据信 ...

  7. SQL Server Replace函数

    REPLACE用第三个表达式替换第一个字符串表达式中出现的所有第二个给定字符串表达式. 语法REPLACE ( 'string_expression1' , 'string_expression2' ...

  8. 再谈Unity调用Android的Activity

    这段时间在研究Unity4.3开发环境下.怎样调用由Android SDK4.4.2写的Activity.參考了非常多网上的博客.百度出了几十篇大部分都是转载雨松MOMO的,这里必须向雨松MOMO表示 ...

  9. 【SR】MAP

    MAP:最大后验概率(Maximum a posteriori) 估计方法根据经验数据获得对难以观察的量的点估计.它与最大似然估计中的 Fisher方法有密切关系, 但是它使用了一个增大的优化目标,这 ...

  10. 5、手把手教React Native实战之盒子模型BoxApp

    用HTML5和React Native分别实现盒子模型显示 写法不一样: 1.样式 ![样式不同](http://image17-c.poco.cn/mypoco/myphoto/20160323/0 ...