1. 程式人生 > 實用技巧 >點陣圖介紹(bitmap)

點陣圖介紹(bitmap)

1、點陣圖(Bitmap)簡介

點陣圖是一種非常常見的結構,它使用每個二進位制位來存放一個值的狀態,正因為這個性質,它經常被用在資料壓縮或者是索引等方面。

有這樣一道題:給40億個不重複的無符號整數,沒有經過排序,然後再給一個樹,如何快速判斷這個數是否在40億個數之中?在這裡如果我們實打實的存放40億個資料在記憶體中,那會佔據將近15個G的記憶體,普通電腦根本無法滿足,更不用說在對其進行查詢操作了。那麼如果選擇點陣圖來儲存的話我們只需要差不多500M就夠了。大大的節省了記憶體的消耗。

如下圖,我們把1表示存在狀態,0表示不存在,那麼該組資料中就標記了2和5兩個數存在

2、C++點陣圖實現

  點陣圖結構需要自己實現,C++並沒有現成的資料結構可以用

  

  一個int型別整數佔4個位元組,一共32位,可以標記32個數的狀態,因此,我們把一個整數佔用的記憶體叫做一個單元,一個單元標記32個數據的狀態

  

  我們對一個數據進行標記之前需要先確定在那個單元,N/32

  在確定在該單元的第幾位上 N%32

  確定位置之後改變狀態

  (0-->1) ,採用或運算

   (1-->0) ,採用與運算

  

#include<iostream>
#include<string.h>
#include<algorithm>
#include 
<vector> #include<bitset> using namespace std; class BitMap { public: //初始化點陣圖的大小,range是要儲存的資料個數,1個int資料可以標記32個狀態,因為點陣圖是不支援擴容操作的 //所以一開始要確定好點陣圖的大小 //比如要標記1000個數據的狀態,需要開int型別的陣列大小為1000/32+1 BitMap(size_t range) { _bits.resize((range >> 5) + 1); } //在點陣圖中標記第N個數據 void
Set(size_t N) { //先確定在那個單元 size_t index = N >> 5; //在確定在該單元的什麼位置 size_t bitNum = N % 32; //或運算對原來為1的狀態沒有影響,方便我們改變第N個數的狀態 _bits[index] |= (1 << bitNum); } //在點陣圖中的第N個數據標記置零 void Reset(size_t N) { size_t index = N >> 5; size_t bitNum = N % 32; //假設bitNum=3,則1<<3 = 1000 // 取反操作 ~(1000) = 0111 _bits[index] &= (~(1 << bitNum)); } //判斷第N個數是否被標記 bool check(size_t N) { //假設N=9,9>>5相當於9/(2^5) size_t index = N >> 5; //bitNum=9 size_t bitNum = N % 32; //_bits[0]= 00000000 00000000 00000010 00000000 //_bits[0>>9=00000000 00000000 00000000 00000001 return (_bits[index] >> bitNum) & 1; } private: vector<int> _bits; }; int main() { BitMap bs(1001); bs.Set(5); bs.Set(63); bool ret = bs.check(33); if (ret) { cout << "它在" << endl; } else { cout << "它不在" << endl; } /*bitset<32>t1(~(9 >> 5)); bitset<32>t2(1 << 9); cout << t1<< endl; cout << t2 << endl;*/ system("pause"); return 0; }

轉載自https://blog.csdn.net/MOU_IT/article/details/89106308?utm_medium=distribute.pc_relevant.none-task-blog-BlogCommendFromMachineLearnPai2-4.channel_param&depth_1-utm_source=distribute.pc_relevant.none-task-blog-BlogCommendFromMachineLearnPai2-4.channel_param