STL detallado (14): introducción y uso del conjunto de bits (mapa de bits)

Introducción al conjunto de bits

La introducción de mapas de bits

Da 4 mil millones de enteros únicos sin signo, sin clasificar. Dado un entero sin signo, ¿cómo determinar rápidamente si un número se encuentra entre los 4 mil millones de números?

Para determinar si un número está en un cierto montón, podemos pensar en los siguientes métodos:

  • Ordene esta pila de números y luego use el método de búsqueda binaria para determinar si el número está en esta pila de números.
  • Inserte esta pila de números en el contenedor unordered_set y luego llame a la función de búsqueda para determinar si el número está en esta pila de números.

Desde el punto de vista del método, ambos métodos son posibles y la eficiencia también es buena. La complejidad temporal del primer método es O ( N log N ) O (NlogN)O ( N l o g N ) , la complejidad temporal del segundo método esO ( N ) O(N)O ( N ) _

Pero el problema es que aquí hay 4 mil millones de números. Si queremos cargar todos estos números en la memoria, ocupará 16 G de espacio y el consumo de espacio es muy grande. Por lo tanto, desde la perspectiva del consumo de espacio, los dos métodos anteriores son realmente inviables.

resolución de mapa de bits

De hecho, en este problema, solo necesitamos juzgar si un número está presente o no, es decir, solo hay dos estados, entonces podemos usar un bit para indicar si los datos existen, si el bit es 1, significa existe, y el bit es 0. Indica que no existe. Por ejemplo, hay 232
inserte la descripción de la imagen aquí
enteros sin signo en total , por lo que registrar estos números requiere 232 bits, lo que equivale a 512 M de espacio de memoria, y el consumo de memoria se reduce considerablemente.

concepto de mapa de bits

El llamado mapa de bits consiste en usar cada bit para almacenar un determinado estado, lo cual es adecuado para escenarios con datos masivos y sin repetición de datos. Por lo general, se utiliza para determinar si un determinado dato existe o no.

aplicaciones de mapa de bits

Las aplicaciones comunes de mapa de bits son las siguientes:

  1. Encuentre rápidamente si un dato está en una colección.
  2. clasificar.
  3. Encuentra la intersección, unión, etc. de dos conjuntos.
  4. Marca de bloque de disco en el sistema operativo.
  5. Bits de marca de señal en el kernel (palabra de máscara de señal y conjunto de señal pendiente).

uso de conjunto de bits

Cómo se define un conjunto de bits

Método 1: construya un mapa de bits de 16 bits, todos los bits se inicializan en 0.

bitset<16> bs1; //0000000000000000

Método 2: construya un mapa de bits de 16 bits e inicialice los primeros n bits del mapa de bits de acuerdo con el valor dado.

bitset<16> bs2(0xfa5); //0000111110100101

Método 3: construya un mapa de bits de 16 bits e inicialice los primeros n bits del mapa de bits de acuerdo con la secuencia 0/1 en la cadena.

bitset<16> bs3(string("10111001")); //0000000010111001

Uso de funciones miembro de conjunto de bits

Las funciones miembro comúnmente utilizadas en el conjunto de bits son las siguientes:

función miembro Función
colocar Establecer el bit especificado o todos los bits
Reiniciar Borrar bit especificado o todos los bits
dar la vuelta Invertir bits especificados o todos los bits
prueba Obtener el estado del bit especificado
contar Obtener el número de bits que se establecen
Talla Obtener el número de bits que se pueden acomodar
ninguna Devuelve verdadero si alguno de los bits está establecido
ninguna Devuelve verdadero si no se establece ningún bit
todos Devuelve verdadero si todos los bits están establecidos

Ejemplo de uso:

#include <iostream>
#include <bitset>
using namespace std;

int main()
{
    
    
	bitset<8> bs;
	bs.set(2); //设置第2位
	bs.set(4); //设置第4位
	cout << bs << endl; //00010100
	
	bs.flip(); //反转所有位
	cout << bs << endl; //11101011
	cout << bs.count() << endl; //6

	cout << bs.test(3) << endl; //1

	bs.reset(0); //清空第0位
	cout << bs << endl; //11101010

	bs.flip(7); //反转第7位
	cout << bs << endl; //01101010

	cout << bs.size() << endl; //8

	cout << bs.any() << endl; //1

	bs.reset(); //清空所有位
	cout << bs.none() << endl; //1

	bs.set(); //设置所有位
	cout << bs.all() << endl; //1
	return 0;
}

Nota: Cuando se utilizan las funciones miembro set, reset y flip, si se especifica un determinado bit, se opera el bit, y si no se especifica ningún bit, se operan todos los bits.

Uso del operador de conjunto de bits

1. El uso de los operadores >> y << en el conjunto de bits.
El contenedor de conjuntos de bits sobrecarga los operadores >> y << Podemos usar directamente los operadores >> y << para realizar operaciones de entrada y salida en los objetos definidos por el contenedor de conjuntos de bits.

#include <iostream>
#include <bitset>
using namespace std;

int main()
{
    
    
	bitset<8> bs;
	cin >> bs; //10110
	cout << bs << endl; //00010110
	return 0;
}

En segundo lugar, el uso de operadores de asignación, operadores relacionales, operadores de asignación compuestos y operadores unarios en conjuntos de bits.
En el contenedor de conjunto de bits, no solo el operador de asignación y algunos operadores relacionales están sobrecargados, sino también algunos operadores de asignación compuestos y operadores unarios están sobrecargados, y podemos usar directamente estos operadores para operar en mapas de bits individuales.

Incluye los siguientes operadores:

  • Operador de asignación: =.
  • Operadores relacionales: ==, !=.
  • Operadores de asignación compuestos: &=, |=, ^=, <<=, >>=.
  • Operador unario: ~.
#include <iostream>
#include <string>
#include <bitset>
using namespace std;

int main()
{
    
    
	bitset<8> bs1(string("10101010"));
	bitset<8> bs2(string("10101010"));
	bs1 >>= 1;
	cout << bs1 << endl; //01010101

	bs2 |= bs1;
	cout << bs2 << endl; //11111111
	return 0;
}

3. El uso de operadores bit a bit en conjunto de bits.
Los tres operadores de bits también están sobrecargados en el contenedor de conjuntos de bits.Podemos usar directamente &, |, ^ para operar en cada mapa de bits.

#include <iostream>
#include <string>
#include <bitset>
using namespace std;

int main()
{
    
    
	bitset<8> bs1(string("10101010"));
	bitset<8> bs2(string("01010101"));
	
	cout << (bs1&bs2) << endl; //00000000
	cout << (bs1|bs2) << endl; //11111111
	cout << (bs1^bs2) << endl; //11111111
	return 0;
}

Cuarto, el uso del operador [ ] en el conjunto de bits.
El operador [ ] está sobrecargado en el contenedor del conjunto de bits, y podemos usar directamente [ ] para acceder o modificar el bit especificado.

#include <iostream>
#include <string>
#include <bitset>
using namespace std;

int main()
{
    
    
	bitset<8> bs(string("00110101"));
	cout << bs[0] << endl; //1
	bs[0] = 0;
	cout << bs << endl; //00110100
	return 0;
}

Supongo que te gusta

Origin blog.csdn.net/chenlong_cxy/article/details/122508805
Recomendado
Clasificación