目次
まず、なぜビットマップとブルーム フィルターが表示されるのでしょうか?
前文
私たちの日常生活においては、ビッグデータの処理が欠かせません。例えば、ゲーム名を登録する際には、そのデータが存在するかどうかをデータベースと照合する必要があります。ビッグデータの処理には、ギリシャの概念に基づいたビットマップやブルームフィルターが使用されます。もちろん、これはそのうちの 1 つです。今回は主にビットマップの概念と実装について説明します。ブルーム フィルターについては後ほど説明します。
まず、なぜビットマップとブルーム フィルターが表示されるのでしょうか?
実生活ではビッグデータの処理は避けられませんが、私たちのデータ構造では、ハッシュ テーブルに基づく unordered_set/unowned_map は非常に効率的なデータ構造ですが、数 g または十数 g のような大きなファイルに直面した場合には、メモリにロードできないと書き込み不足が発生するため、ハッシュの考え方を継承したビットマップとブルームフィルターが誕生しました。
2、ビットマップ/BitSet
2.1 ビットマップとは
ビットマップを正式に導入する前に、テンセントの典型的な面接の質問を見てみましょう。
上の図に示すように、これを見た生徒はどうしますか? 共通のアイデアは 2 つあります。
1. トラバース、時間計算量 O(N)
2. ソートしてから二分探索を使用し、時間計算量 O(NlogN+logN)
上記 2 つの方法は、正常な問題の有無の判断には非常に有効ですが、この質問には 40 億個の整数があり、160 億バイト、つまり 16G に相当します。まったく記憶がないのですが、どう対処すればよいでしょうか?ここではこのように解決できます
3. ビットマップソリューション
0、1 を使用して整数データが存在するかどうかを表すことができるため、次の図に示すように整数をビットにマッピングできます。
したがって、ビットマップの概念は次のとおりです
いわゆるビットマップは、各ビットを使用して特定の状態を保存するもので、大量のデータがあり、データが繰り返されないシナリオに適しています。通常、
特定のデータが存在するかどうかを判断するために使用されます
2.2 ビットマップの実装
ここでは、set (挿入)、reset (削除)、test (検索) という3 つの基本関数を備えたビットマップ構造を実装します。
まず第一に、ビットマップは 1 つのデータに対応する 1 ビットであるため、スペースを開くとき、データが N 個ある場合、N ビットのスペースを開く必要があり、これによりスペースが大幅に節約されます。当初は 40 億を読み取りました。整数には 16G のメモリが必要です。 40 億ビットのスペースが空きます。必要なのは 500M だけで、スペースが大幅に節約されます。
次に、組み込み型は char - 1 バイト - 8 ビット、int - 4 バイト - 12 ビットです。ここでは、データを見つけやすくするために、基本単位として char を選択します。
最後に、データがマッピングされている場所を見つけるには、次の式を使用できます。
//定位到第i个char
int i = N / 8
//定位到第i个char的第j个位
int j = n % 8
位置を特定した後、ビットごとの & (0 に対応する補数コードを比較して 0 で、両方とも 1 であれば 1)、ビットごと | それは 0、それは 0) を使用します。 待機動作によりデータの挿入、削除、検索が完了します
以上の考えをもとに、以下のような図を描きました。
実装コードは以下の通り
template <size_t N>//N为要数据量
class BitSet
{
public:
//构造函数
BitSet()
{
_bs.resize(N / 8 + 1, 0);//这里多开一个char的原因是
//因为/号可能省去了余数,因此需要多开一个
//如10/8=1,但实际上还有2个数据,因此需要多开一个
}
//插入
void set(size_t number)
{
size_t i = number / 8;
size_t j = number % 8;
//插入
_bs[i] |= (1 << j);
}
//删除
void reset(size_t number)
{
size_t i = number / 8;
size_t j = number % 8;
//删除
_bs[i] &= ~(1 << j);
}
//查找
bool test(size_t number)
{
size_t i = number / 8;
size_t j = number % 8;
return _bs[i] & (1 << j);
}
private:
vector<char> _bs;
};
テスト例でこれをテストできます
void test_bitset1()
{
BitSet<100> bs;
bs.set(10);
bs.set(11);
bs.set(15);
cout << bs.test(10) << endl;
cout << bs.test(15) << endl;
bs.reset(10);
cout << bs.test(10) << endl;
cout << bs.test(15) << endl;
bs.reset(10);
bs.reset(15);
cout << bs.test(10) << endl;
cout << bs.test(15) << endl;
}
完璧に動作します
3、ビットマップの長所と短所
3.1 ビットマップの利点
1. マッピング関係に従って検索し、時間計算量はビット (O(1)) であり、効率が高い
2. 整数データを直接ロードする場合に使用されるスペースと比較して、ビットマップはスペースを大幅に節約します
3.2 ビットマップの欠点
1. マッピングできるのは整数データのみで、それ以外の文字列などについては何もできません。
要約する
以上が、このセクションのビットマップの内容のすべてです ビットマップの利点は非常に強力ですが、欠点も明らかであり、文字などの他の側面に適用することができません。もちろんあります、この度、ブルームフィルターがデビューする予定です、ベテランの皆様、楽しみにしていてください