點陣圖和雜湊切分的大資料處理
阿新 • • 發佈:2018-12-25
點陣圖是一個數組的每個資料的每個二進位制位表示一個數據,0表示資料不存在,1表示資料存在;
在現實生活中,大資料的處理十分的常見;比如說,給40億個不重複的無符號整數,沒排過序,如何快速判斷一個數是否在這40億個數中?
要解決這個問題,我們首先想到的是先排序,在進行二分查詢,很容易就可以判斷成功。但是排序並不好排,40億個資料,讓我們來算一算需要多少的記憶體,40億*4位元組 = 4G*4 = 16G;一般的電腦都是4G,8G;一次處理16G的資料顯然是不可能了;這就需要用點陣圖來解決這類的問題了;
要表示40億個資料,一個數據4個位元組,32個二進位制位,用一個二進位制位來表示一個數是否存在的狀態,這就需要500M左右的記憶體;顯然這是可以接受的;具體看下圖:
實現程式碼如下:
解決上述問題的測試用例://點陣圖 class BitSet { public: BitSet(const size_t range) { _a.resize((range>>5) + 1); } void Set(size_t num) //將num記錄; { size_t index = num >> 5; size_t pos = num % 32; _a[index] |= (1 << pos); } void Reset(size_t num) //刪除num記錄 { size_t index = num >> 5; size_t pos = num % 32; _a[index] &= ~(1 << pos); } bool Test(size_t num) //判斷num是否存在; { size_t index = num >> 5; size_t pos = num % 32; //判斷這這個位,0不存在,1存在; return _a[index] & (1 << pos); } protected: vector<int> _a; };
void TestBitSet()
{
BitSet bs(-1); //-1轉換後就是整數表示的最大範圍;
bs.Set(1);
bs.Set(3);
bs.Set(4);
bs.Set(8);
//.... 向後的40億資料
cout << bs.Test(1) << endl;
cout << bs.Test(10) << endl;
}
讓我們繼續深入,看看另外一個問題:
給一個超過100G大小的log file,log中存著ip地址,設計演算法找到出現次數最多的IP地址?
一次處理100G,計算機想想就壓力巨大,我們可以將其劃分位計算機能處理的大小進行處理,比如以1G為單位劃分位100份,一份一份進行處理,就可達到目的,但是怎麼劃分是個難題;
第一種思路:可以將100G等分劃分位100份,每一份單獨處理,但是這個會遇到一個問題,有些想同的IP地址是在不同的等分塊中,統計的結果不是正確的結果;
第二種思路:利用雜湊切分,可以劃分成100份,重點是使相同IP進入一個編號相同的小檔案;這就避免了相同IP地址分散在不同小檔案的問題;