最近在看《程式設計珠璣》這本書。 第1章中引入了bitmap(位圖)的資料結構。以前沒有接觸過, 抽空研究了一下,記錄下來。
書中描述的情景:
1. 最多1000萬個7位數**號碼(號碼不重複,實際大概800萬個),儲存在文字中
2. 每隔一段時間要對號碼進行排序
3.程式模組最多可用1m bytes的記憶體, 磁碟空間充足
分析:通常方案:7位**號碼可以用uint32_t (4個位元組)來儲存, 4 * 8 * 10^6 bytes約為32m bytes,一次性排序顯然記憶體不滿足。
1m bytes 記憶體可以存放 10^6/4 = 250萬個號碼, 1000萬個約要分40趟進行讀取排序寫入檔案,在歸併到一起
此方案,需要40次讀原始文字的代價,效率低下。
位圖方案: 1個位元組(8bit)可以存放8個整數, 實際800萬個號碼,剛好1m bytes的記憶體空間可以使用,符合要求。
一、原理
通常儲存方案, 每個整數(假如4個位元組), 占用記憶體多, 在記憶體不足或海量資料時, 導致處理方法複雜。
位圖, 可以理解用位(bit)來表示資料, 1個位元組是8位, 可以儲存8個連續的整數, 記憶體空間充分利用。 每一位 1表示有資料, 0 表示沒有資料。
舉例說明:
整數集合
5個整數,用通常儲存方案,需要 5 * 4 = 20 位元組
點陣圖只需要 12位, 不到2個位元組(通常是用2個位元組來存放,方便管理和位元組對齊)
這5個整數用位圖表示如下:01
0000
0101
1100
000 12
3456
78910
1112
1314
15第1個位元組,表示的資料範圍 0 ~ 7; 第2個位元組, 表示的資料範圍 : 8 ~ 15
二、 乙個非負整數(假設為n)點陣圖的表示方法
(負數表示的方法類似, 在此只以非負數來分析)
1. 計算n屬於哪個單元
1個位元組(8bit)可以存放8個連續的整數,乙個位圖可以劃分為多個這樣的小單元。
整數n除以8 的值可以判斷在哪個單元中。
如例子中: 整數 9, 9 / 8 = 1(從0 開始計算的),可以知道在第2個位元組單元中。
2. 點陣圖中n的插入
每乙個位元組中,可以表示8個連續整數, 要確定n在單元中的確切位置
插入9之前: 00
0000
0089
1011
1213
1415
插入9之後: 01
0000
0089
1011
1213
1415
假設插入之前,單元數值為x,
插入9後可以表示為: x | (0x80 >> 9 % 8)
公式可以表示為: x | ( 0x80 >> n % 8)
推算過程: 0x80, 二進位制表示 1000 0000 ,右移 9 % 8= 1位, 變為 0 100 0000,和 插入之前的數 「或」運算,就可以把9的位置設為1了。
3. 點陣圖中n的查詢
假設n 所在的劃分單元的數值為 x,
公式可以表示為: x & ( 0x80 >> n % 8)
推算過程:0x80 右移 n % 8 位, 與x 進行「交」運算, 如果結果為0, 則整數n不在位圖中, 反之,在位圖中。
4. 點陣圖中n的刪除
假設n所在的劃分單元的數值為x,
公式可以表示為: x & ~(0x80 >> n % 8)
推算過程:0x80 右移 n % 8 位,求反會把對應的為置為0,其他位為1, 再與x 進行「交」運算, 只把n所在單元的位置設為0
通過以上的分析,寫**就方便了。 我用c語言寫了乙個簡單的測試**:
_bitmap.h
test.c#ifndef _bitmap_h
#define _bitmap_h
#include
static
inline
void
bitmap_add
(char* p, int64_t n)
static
inline
void
bitmap_del
(char* p, int64_t n)
// yes: > 0, no: 0
static
inline
intbitmap_lookup
(char* p, int64_t n)
#endif
/*_bitmap_h*/
輸出結果:#include
#include
"_bitmap.h"
intmain
(int argc, char* ar**)
;#define size 1000
char a[size] = ;
// can store 0 ~ 7999
int i =
0;for (i =
0; i <
sizeof(num) /
sizeof(
uint32_t); i++)
//print bitmap
char* p = a;
for (i =
0; i < size; i++)
p++;
}printf(
"\n");
// delete
bitmap_del(a,
99);
bitmap_del(a,
0);// print bitmap
p = a;
for (i =
0; i < size; i++)
p++;
}printf(
"\n");
int x =
99;if (bitmap_lookup(a, x))
else
x =
7999;
if (bitmap_lookup(a, x))
else
return
0;
}
資料結構 BitMap
問題 已知有n個整數,這些整數的範圍是 0,100 請你設計一種資料結構,使用陣列儲存這些資料,並提供兩種方法,分別是addmember和i ist.下面是這種資料結構的類的定義。思路1 用陣列儲存,查詢是否存在需要for迴圈n,有n個數那麼複雜度為o n 思路2 用陣列儲存,新增資料則arr in...
資料結構之BITMAP
給40億個不重複的無符號整數,沒排過序。給乙個無符號整數,如何快速判斷乙個數是否在這40億個數中。這個問題怎麼解決呢?1 將40億資料儲存起來 儲存在陣列 鍊錶 樹中 再和該數判斷是否相等。那我們思考一下需要多少記憶體 2 借助點陣圖bitmap解決。位圖 bitmap 是用乙個陣列中的每個資料的每...
C 實現BitMap資料結構
分治,分布式。bitmap 位圖 及其公升級版bloom filter是處理海量資料常用的方法,這裡先介紹bitmap概念及其c 實現。一 bitmap點陣圖 該資料結構描述了乙個有限定義域內的稠密集合,其中的每乙個元素最多出現一次並且沒有其他任何資料與該元素相關聯。即使這些條件沒有完全滿足 例如,...