Introducción y simulación de mapa de bits de conjunto de bits en la sintaxis de C++

1. Introducción de mapa de bits

Echemos un vistazo a la siguiente pregunta de la entrevista:

Dé 4 mil millones de enteros únicos sin signo, no ordenados. Dado un entero sin signo, cómo determinar rápidamente si un número está entre los 4 mil millones de números.

Después de nuestro estudio previo, podemos tener las siguientes ideas:

  • Ordene estos números y luego use el algoritmo binario para encontrar si este número existe
  • Inserte en unordered_set, use la función de búsqueda para averiguar si existe

El método anterior se ve bien, la complejidad de tiempo del algoritmo de búsqueda binaria es logN, y la complejidad de tiempo de inserción en unordered_set es O(N), y la complejidad de tiempo de búsqueda es O(1), pero existe el problema de que el Espacio insuficiente, 4 mil millones de enteros sin signo necesitan 16 mil millones de bytes de espacio, que es aproximadamente 16 GB de espacio. Generalmente, la promoción interna de las computadoras es 4G u 8G, por lo que no hay espacio suficiente. En este momento, hay un método de mapa de bits para resolver eso:

Ya sea que los datos estén en los datos plásticos dados, el resultado esté o no, se trata de dos estados, entonces puede usar un bit binario para representar la información de si los datos existen, si el bit binario es 1, significa existe, y si es 0, significa que no existe. Por ejemplo:

Para la imagen de arriba, hay una matriz de enteros, podemos usar el método de direccionamiento directo para mapear los datos de la matriz, pero a diferencia de antes, solo se usa un bit para representar los datos de un entero en este momento, cuando este número existe, el la posición del bit es 1. Si no existe, la posición del bit es 0. En este momento, los recursos de espacio se pueden ahorrar mucho. y un espacio es un bit, por lo que al final, solo se necesitan 512 MB de espacio. Pero no podemos espaciar por bit, se requiere al menos un byte, por lo que abrimos un espacio de byte a la vez, es decir, 8 bits, y tratamos 8 bits como un todo, y dividimos los datos que se guardarán por 8. Para el número de bytes, el módulo 8 de los datos guardados es el número de posiciones en este byte.

En segundo lugar, el concepto de mapa de bits

El llamado mapa de bits consiste en utilizar cada bit para almacenar un determinado estado, lo que es adecuado para escenarios en los que hay una gran cantidad de datos y los datos no se repiten. Por lo general, se utiliza para juzgar si un determinado dato existe o no.

Entonces, ¿cuáles son las otras aplicaciones de los mapas de bits?

  • Encuentre rápidamente si ciertos datos están en una colección
  • Ordenar + deduplicar
  • Encuentra la intersección, unión, etc. de dos conjuntos
  • Marcado de bloque de disco en el sistema operativo

Implementación de simulación de mapa de bits

1. Constructor

由于不能按位开空间,所以我们选择每次开一个字节的空间,由于有范围最大为N,一位关联一个数据,所以需要开N/8个字节的空间,但是有时可能不能整除,所以要开N/8+1个字节的空间。所以

直接在构造函数中开好空间:

bitset()
		{
			_bits.resize(N / 8 + 1,0);
		}

二、set,reset,test函数

set函数的作用是对位图中的某一位进行填充

i就表示是第几个字节,而j表示该位在该字节中的第几位,所以对1进行左移j位后与该字节按位或,按位或的作用时不论该位为0还是为1,都将该位变为1。

void set(size_t x)
		{
			int i = x / 8;
			int j = x % 8;
			_bits[i] |= (1 << j);
		}

reset的作用是将某一位清空

同样的将要清空的那一位置为0,进行按位与,不论原本该位是0还是1,都将该位置0

void reset(size_t x)
		{
			int i = x / 8;
			int j = x % 8;
			_bits[i] &= ~(1 << j);
		}

test的作用是检测位图中某一位是否存在

bool test(size_t x)
		{
			int i = x / 8;
			int j = x % 8;
			return _bits[i] & (1 << j);
		}

三、代码测试

void test_bit_set1()
	{
		bitset<100> bs1;
		bs1.set(8);
		bs1.set(9);
		bs1.set(20);
		cout << bs1.test(8) << endl;
		cout << bs1.test(9) << endl;
		cout << bs1.test(20) << endl;
		bs1.reset(8);
		bs1.reset(9);
		bs1.reset(20);
		cout << bs1.test(8) << endl;
		cout << bs1.test(9) << endl;
		cout << bs1.test(20) << endl;
	}

四、完整代码

namespace tmt
{
	template<size_t N>
	class bitset
	{
	public:
		bitset()
		{
			_bits.resize(N / 8 + 1,0);
		}
		void set(size_t x)
		{
			int i = x / 8;
			int j = x % 8;
			_bits[i] |= (1 << j);
		}
		void reset(size_t x)
		{
			int i = x / 8;
			int j = x % 8;
			_bits[i] &= ~(1 << j);
		}
		bool test(size_t x)
		{
			int i = x / 8;
			int j = x % 8;
			return _bits[i] & (1 << j);
		}
	private:
		vector<char> _bits;
	};
	void test_bit_set1()
	{
		bitset<100> bs1;
		bs1.set(8);
		bs1.set(9);
		bs1.set(20);
		cout << bs1.test(8) << endl;
		cout << bs1.test(9) << endl;
		cout << bs1.test(20) << endl;
		bs1.reset(8);
		bs1.reset(9);
		bs1.reset(20);
		cout << bs1.test(8) << endl;
		cout << bs1.test(9) << endl;
		cout << bs1.test(20) << endl;
	}

Supongo que te gusta

Origin juejin.im/post/7266310505920053260
Recomendado
Clasificación