位图算法定义
位图法就是bitmap的缩写,所谓bitmap,是用每一位来存放某种状态,适用于大规模数据,但数据状态又不是很多的情况,通常是用来判断某个数据存不存在的。这种算法在操作系统内核(Linux、RTThread、AliOS Things等)源码中会经常看到,所有很有必要去研究下这种算法,这样可以有助于阅读和分析内核源码。
位图其实是用数组实现的,数组的每一个元素的每一个二进制位都可以表示一个数据在或者不在,0表示数据存在,1表示数据不存在。因为比特位只有两种状态,要不是0,要不就是1,所以位图其实就是一种直接定址法的哈希,只不过位图只能表示这个值在或者不在。
位图数据结构
unsigned int bit[N];
在这个数组里面,可以存储 N * sizeof(int) * 8个数据,但是最大的数只能是N * sizeof(int) * 8 - 1。假如,我们要存储的数据范围为0-31,则我们只需要使得N=1,这样就可以把数据存进去
假如有一个待排序的数组:
int a[] = {17, 7, 10, 30 };
位图算法实现
字节位置=数据/32;(采用位运算即为右移5位)
位位置=数据%32;(采用位运算即跟0X1F进行与操作,因为0X1F=00011111,将一个数和0X1F相与就是将32的倍数全部清零,只留下余数位。)
- 将所有的位都置为0,从而将集合初始化为空。
- 通过读入文件中的每一个整数来建立集合,将每一个对应的位置都置为1.
- 检查每一位,如果该位为1,就输出对应的整数,由此产出有序的输出文件。
AliOS Things位图实现
#define BITMAP_UNIT_SIZE 32U
#define BITMAP_UNIT_MASK 0X0000001F
#define BITMAP_UNIT_BITS 5U
/*bit位置,这个地方做了一次反转*/
#define BITMAP_MASK(nr) (1UL << (BITMAP_UNIT_SIZE - 1U - ((nr) & BITMAP_UNIT_MASK)))
/*字节位置*/
#define BITMAP_WORD(nr) ((nr) >> BITMAP_UNIT_BITS)
/**
* Declare a bitmap for task priority.
*
* @param[in] name the name of the bitmap to declare
* @param[in] bits the bits of the bitmap
*
* @return no return
*/
#define BITMAP_DECLARE(name, bits) uint32_t name[((bits) + (BITMAP_UNIT_SIZE - 1U)) >> BITMAP_UNIT_BITS]
/**
* Set a bit of the bitmap for task priority.
*
* @param[in] bitmap pointer to the bitmap
* @param[in] nr position of the bitmap to set
*
* @return no return
*/
RHINO_INLINE void krhino_bitmap_set(uint32_t *bitmap, int32_t nr)
{
bitmap[BITMAP_WORD(nr)] |= BITMAP_MASK(nr);
}
/**
* Clear a bit of the bitmap for task priority.
*
* @param[in] bitmap pointer to the bitmap
* @param[in] nr position of the bitmap to clear
*
* @return no return
*/
RHINO_INLINE void krhino_bitmap_clear(uint32_t *bitmap, int32_t nr)
{
bitmap[BITMAP_WORD(nr)] &= ~BITMAP_MASK(nr);
}
总结
位图算法,其需要一次遍历整个数据,假如有N个数据,就只是需要遍历N次,所以时间复杂度
是 O(N)。但是,其需要额外地开辟内存空间,有N个数据,就需要多开辟N bit位的数据。