位圖算法定義
位圖法就是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位的數據。