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()就可以实现查重功能。
第一次写博客,肯定有很多问题和不足,希望大家不吝赐教。