大きなデータファイルをどのように処理しますか? ビットマップとブルーム フィルターを見てみましょう (パート 1)

目次

前文

まず、なぜビットマップとブルーム フィルターが表示されるのでしょうか?

2、ビットマップ/BitSet

2.1 ビットマップとは

2.2 ビットマップの実装

3、ビットマップの長所と短所

3.1 ビットマップの利点

3.2 ビットマップの欠点

要約する


前文

私たちの日常生活においては、ビッグデータの処理が欠かせません。例えば、ゲーム名を登録する際には、そのデータが存在するかどうかをデータベースと照合する必要があります。ビッグデータの処理には、ギリシャの概念に基づいたビットマップやブルームフィルターが使用されます。もちろん、これはそのうちの 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. マッピングできるのは整数データのみで、それ以外の文字列などについては何もできません。

要約する

以上が、このセクションのビットマップの内容のすべてです ビットマップの利点は非常に強力ですが、欠点も明らかであり、文字などの他の側面に適用することができません。もちろんあります、この度、ブルームフィルターがデビューする予定です、ベテランの皆様、楽しみにしていてください

おすすめ

転載: blog.csdn.net/zcxmjw/article/details/131002473