位图排序

来源:互联网 发布:剑网3数据非法 编辑:程序博客网 时间:2024/05/02 06:07

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

位图算法称的上是最简单的算法,只需要一个for循环就能够搞定排序和查找,但是同时它也是对待操作的数据要求最苛刻的 ,首先这些数据必须是正整数,其次要大致知道这些数据的范围,且有一定的聚集性。

 位图排序是一种效率极高(复杂度可达O(n))并且很节省空间的一种排序方法,但是这种排序方法对输入的数据是有比较严格的要求(数据不能重复,大致知道数据的范围)。位图排序即利用位图或者位向量来表示集合。举个例子,假如有一个集合{3,5,7,8,2,1},我们可以用一个8位的二进制向量set[1-8]来表示该集合,如果数据存在,则将set相对应的二进制位置1,否则置0.根据给出的集合得到的set为{1,1,1,0,1,0,1,1},然后再根据set集合的值输出对应的下标即可得到集合{3,5,7,8,2,1}的排序结果。这个就是位图排序的原理。

位图法定义

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

位图法应用

一、给40亿个不重复的unsigned int的整数,没排过序的,然后再给一个数,如何快速判断这个数是否在那40亿个数当中
申请512M的内存
一个bit位代表一个unsigned int值
读入40亿个数,设置相应的bit位
读入要查询的数,查看相应bit位是否为1,为1表示存在,为0表示不存在
二、使用位图法判断整形数组是否存在重复
判断集合中存在重复是常见编程任务之一,当集合中数据量比较大时我们通常希望少进行几次扫描,这时双重循环法就不可取了。
位图法比较适合于这种情况,它的做法是按照集合中最大元素max创建一个长度为max+1的新数组,然后再次扫描原数组,遇到几就给新数组的第几位置上1,如遇到 5就给新数组的第六个元素置1,这样下次再遇到5想置位时发现新数组的第六个元素已经是1了,这说明这次的数据肯定和以前的数据存在着重复。这种给新数组初始化时置零其后置一的做法类似于位图的处理方法故称位图法。它的运算次数最坏的情况为2N。如果已知数组的最大值即能事先给新数组定长的话效率还能提高一倍。
三、使用位图法进行整形数组排序
四、位图法存数据
因为需要用到位运算,所以位图法只适用于正整数的排序及查找.



相关位操作:与& , 或|, 异或^, 非!.
移位操作: << 左移,右移>>

方法介绍:
假设有数组 int array[5] = {2,5,3,6,1}
由于最大值为6,我们只需一个int 型变量作为位图便可将这些整数存放于位图之中。
int bitmap=0; (32 bits)
该位图能表示的整数范围为: 0-31

那么该如何在位图中存储数组元素的信息呢?
1. 首先我们将数组中的每个整数用另一种方式表示。将1(即0x0000 0001)左移a[i]位
2.然后将所得结果和bitmap进行或操作
3.存储数组元素的时间复杂度为O(n),其中n为数组长度;

for (int i=0;i<5;i++)
bitmap = bitmap|(1<<a[i]);

e.g.:
当i=0时, 
bitmap的值为0000 0000 0000 0000 0000 0000 0000 0100 
(第2位为1,表示数组中有数值为2的元素)
当数组中所有数均进行同样的操作后,
bitmap的值为0000 0000 0000 0000 0000 0000 0110 1110

如何通过bitmap的值得到数组所含元素呢?
查看数值i 是否存储在bitmap中的方法:
for(int i=0;i< MAX_VALUE;i++)
{
if((bitmap>>i)&1)
     {
//value i  is in the array, order by asc 
cout<<i<<"exists in the array!"<<endl;
}
}

应用场景:1. 数组排序,将元素按照此方法存入位图中,再从位图中输出元素,即为升序排列的元素 时间复杂度为2O(N),其中N 为数组长度
2. 两数组求交集。用两位图,然后对两位图进行与运算,可得两数组的交集 


     
          

1 0
原创粉丝点击