BitMap 学习---- 排序和查重

一、基本介绍

  所谓的Bit-map就是用一个bit位来标记某个元素对应的Value, 而Key即是该元素。由于采用了Bit为单位来存储数据,因此在存储方面,可以大大节省。

上图,图总是比文字更加容易理解一些。

图中表示一个byte,用相应的下标表示Key值;比如我们的数据中存在 0 、3 、6、7,对应的bit就置1.其他数据没有就置0如下图:

在一般的PC中,存储一个整型数据组要4个字节的空间,若使用上述方法,只需要一个字节的空间就足够了。BitMap的存储方式当然会带来一些问题,比如当数据非常稀疏,数据之间的间隔很大(1、100000、200000这样的序列存储比正常存储占用的空间更大),但是对于数据的排序和查重却又很大的帮助。

二、简单应用--排序、查重

1.对于Bit的操作

  位操作的速度非常快,合理适度的运用位操作可以让我们的代码变得更加快速高效。介绍三种BitMap使用的位操作:与操作、或操作、取反操作。

      首先,与操作。基本原理:1&1 = 1,0 & 0 =0,1 & 0 = 0。与操作的运算符是 &;A & B 既是A和B按位与。继续上图:

使用与操作我们可以将某一个bit置0。具体代码如下:

 1 int bitmap_setZero(int index)
 2 {
 3     int line = (index)/8;
 4     int inside_sque = (index)%8;
 5     unsigned char one = ~(0x01 << inside_sque);   //取反操作见下面代码
 6     if(line > Size)
 7        return 0;
 8     bitmap[line] &= one;
 9     return 1; 
10 }

 

      然后,或操作。基本原理:1 | 1 = 1,0 | 0 =0,1 | 0 = 1。或操作的运算符是 |;A | B 既是A和B按位或。再上图:

使用或操作我们可以将某一个bit置1。具体代码如下:

 1 int bitmap_setOne(int index)
 2 {  
 3     int line = (index)/8 ;                         //得到数对应的char
 4     int inside_sque = (index) & 0x07;              // char内部对应的位置
 5     unsigned char one = (0x01<<inside_sque);       //C 语言中没有byte 用 unsigned char 代替
 6     if( line > Size)
 7         return 0;
 8     bitmap[line] |= one;
 9     return 1;
10 }

 

  最后,取反操作,基本原理 ~1 = 0,~0 =1.取反操作的运算符~;~A既是对A按位取反。

2.具体实现

      基本原理搞定,那就可以对一组数据进行排序了。使用Bitmap_setZero(),对Bit数组进行初始化;使用Bitmap_setOne,可以将某一个数存入对应的Bit数组中,当全部数据存入数组后,排序完成,时间复杂度只有O(n)。整体代码如下:

 1 #include <stdio.h>   
 2 #include <stdlib.h>   
 3 #include <string.h> 
 4  
 5 unsigned char *bitmap = NULL;        //  一维的指针 在此应当看做二维 
 6   
 7 int bitmap_setOne(int index)  
 8 {  
 9     int line = (index)/8 ;          
10     int inside_sque = (index)%8;     
11     unsigned char one = (0x1<<inside_sque);   
12     bitmap[line] |= one;  
13     return 1;   
14 }  
15   
16 int bitmap_get(int index)  
17 {  
18     int line = (index)/8 ;          
19     int inside_sque = (index)%8;     
20     unsigned char one = (0x1<<inside_sque);   
21     unsigned char res;  
22     
23     res = bitmap[line] & one;  
24     return res > 0 ? 1 : 0;   
25 }  
26 
27 int bitmap_setZero(int index)
28 {
29     int line = (index)/8 ;          
30     int inside_sque = (index)%8;    
31     unsigned char one = ~(0x1<<inside_sque);   
32     bitmap[line] &= one;  
33     return 1;   
34 }
35   
36 int bitmap_data(int index)  
37 {  
38     return (index );  
39 }  
40   
41 int bitmap_free()  
42 {  
43     free(bitmap);  
44 }   
45 
46 int main()  
47 {  
48     int a[] = {5,8,7,6,3,1,10,78,56,34,23,12,43,54,65,76,87,98,89,100};  
49     int i;  
50     
51     bitmap = (char *)malloc((100/8+1)*sizeof(char));   
52     memset(bitmap, 0x0, 100);  
53  
54     for(i=0; i<20; i++)  
55         printf("%d ",a[i]);
56         printf("\n");
57         
58     for(i=0; i<20; i++)  
59         bitmap_setOne(a[i]); 
60          
61     for(i=0; i<=100; i++)  
62     {  
63         if(bitmap_get(i) > 0 )  
64             printf("%d ", bitmap_data(i));  
65     }  
66     printf("\n");
67     bitmap_free();  
68     getchar();
69     system("PAUSE");
70     return 0;  
71 }  

3. 查重的原理和上面是一样的,其实Bitmap_get()就可以实现查重功能。

 

    第一次写博客,肯定有很多问题和不足,希望大家不吝赐教。

 

转载于:https://www.cnblogs.com/tju-gsp/archive/2013/04/06/Hidden.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值