位图算法

简介:

位图法定义

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

例如,要判断一千万个人的状态,每个人只有两种状态:男人,女人,可以用0,1表示。那么就可以开一个int数组,一个int有32个位,就可以表示32个人。操作的时候可以使用位操作。

欢迎关注我的个人博客:www.wuyudong.com, 更多云计算与大数据的精彩文章

数据结构

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;
}
目录
相关文章
|
机器学习/深度学习 人工智能 自然语言处理
图算法的应用
图算法的应用
158 0
|
存储 算法 调度
基本的算法(续 1)之图算法下
基本的算法(续 1)之图算法
67 0
|
存储 算法 搜索推荐
基本的算法(续 1)之图算法上
基本的算法(续 1)之图算法
75 0
|
算法
【算法】位图算法
【算法】位图算法
|
9月前
|
存储 算法 数据管理
【C/C++ 基础算法】 C/C++ 位图算法的使用
【C/C++ 基础算法】 C/C++ 位图算法的使用
152 0
|
存储 算法
算法导论——基本的图算法
  对于图G=(V,E),V代表点,E代表边。图有两种标准的表示方法:邻接矩阵法和邻接链表法。   邻接链表法适合表示边的条数少的稀疏图,可以节约存储空间。对于有向图G来说,边(u,v)一定会出现在链表Adj[u]中,因此,所有链表的长度之和一定等于|E|。
1767 0
|
算法
一步一步写算法(之图结构)
原文: 一步一步写算法(之图结构) 【 声明:版权所有,欢迎转载,请勿用于商业用途。  联系信箱:feixiaoxing @163.com】      图是数据结构里面的重要一章。
872 0
|
算法 C++ 容器
【基础算法训练】—— 深度优先搜索
【基础算法训练】—— 深度优先搜索
145 0
【基础算法训练】—— 深度优先搜索
|
8月前
|
数据采集 算法 Java
Java数据结构与算法:图算法之广度优先搜索(BFS)
Java数据结构与算法:图算法之广度优先搜索(BFS)
|
存储 并行计算 算法
基于最小生成树的实时立体匹配算法简介
转载请注明出处:http://blog.csdn.net/wangyaninglm/article/details/51533549, 来自: shiter编写程序的艺术 图割,置信传播等全局优化立体匹配算法,由于运算过程中需要迭代求精,运算时间长,无法达到实时计算立体匹配的需求,然而实时性需求却广泛存在立体匹配的应用场景中。
1374 0

热门文章

最新文章