목차
1. 비트맵 소개
비트맵의 기본 아이디어는 비트를 사용하여 요소에 해당하는 값을 표시하고 키는 요소입니다. 데이터를 Bit 단위로 저장하기 때문에 저장 공간을 크게 절약할 수 있습니다. (PS: 저장 공간 절약에 초점)
다음과 같은 요구 사항이 있다고 가정합니다. 20억 개의 임의 정수 중 특정 숫자 m이 존재하는지 확인하고 32비트 운영 체제, 4G 메모리를 가정합니다.
Java에서 int는 4바이트를 차지하며 1바이트 = 8비트(1바이트 = 8비트)
각 숫자를 int에 저장하면 20억 int이므로 점유 공간은 약 (2000000000*4/1024/1024/1024)≈7.45G입니다.
비트 단위로 저장한다면 다릅니다 20억 숫자는 20억 비트이고 점유 공간은 약 (2000000000/8/1024/1024/1024)≈0.233G 입니다
.
자, 여기서 질문이 옵니다. 어떻게 숫자를 나타낼까요?
방금 말했듯이 각 비트는 숫자를 나타내며 0은 존재하지 않는다는 것을 의미하고 1은 존재한다는 것을 의미하므로 이진수와 정확히 일치합니다.
이런 식으로 숫자 {1, 2, 4, 6}을 쉽게 나타낼 수 있습니다.
컴퓨터 메모리 할당의 최소 단위는 바이트(8비트)이므로 {12, 13, 15}를 나타내려면 어떻게 해야 합니까? ?
물론 또 다른 8비트로 표현된다.
이 경우 2차원 배열이 되는 것 같다.
하나의 int는 32비트를 차지하므로 저장할 길이가 int tmp[1+N/32]인 int 배열만 적용하면 됩니다. 여기서 N은 저장할 이러한 숫자의 최대값을 나타냅니다.
tmp[0]: 0~31을 나타낼 수 있음
tmp[1]: 32~63을 나타낼 수 있음
tmp[2]: 64~95를 나타낼 수 있음
。。。
이런 식으로 임의의 정수 M이 주어지면 M/32는 첨자를 얻고 M%32는 이 첨자에서 그것이 어디에 있는지 알 것입니다
1. 추가
여기에 문제가 있습니다. 숫자를 어떻게 입력합니까? 예를 들어 숫자 5를 넣고 싶다면 어떻게 해야 할까요?
먼저 5/32=0, 5%32=5, 이는 tmp[0]의 다섯 번째 위치에 있어야 함을 의미하고 1을 왼쪽으로 5비트 이동한 다음 비트 단위 또는
바이너리로 변환하면
이것은 86 | 32 = 118과 동일합니다.
86 | (1<<5) = 118
b[0] = b[0] | (1<<5)
즉, 숫자를 삽입하려면 숫자를 나타내는 비트를 왼쪽으로 1 이동한 다음 원래 숫자와 비트 단위 OR 연산을 수행합니다.
단순화하면 86 + (5/8) | (1<<(5%8))
따라서 공식은 다음과 같이 요약할 수 있습니다.
2. 클리어
위 내용은 추가사항인데 지우고 싶으면 어떻게 해야 하나요?
여전히 위의 예에서 6을 제거하고 싶다고 가정하면 어떻게 해야 합니까?
그림에서 숫자의 위치를 0으로 설정하면 됩니다.
1은 왼쪽으로 6비트 이동하여 숫자 6으로 표현되는 비트에 도달한 다음 비트 반전을 수행하고 마지막으로 원래 숫자와 비트 AND를 수행하여 위치를 0으로 설정합니다.
b[0] = b[0] & (~(1<<6))
b[0] = b[0] & (~(1<<(i%8)))
3. 찾기
앞에서 각 비트는 숫자를 나타내고 1은 예(또는 존재)를 의미하고 0은 아니오(또는 존재하지 않음)를 의미한다고 말했습니다. 값을 1 또는 0으로 설정하여 추가 및 삭제를 수행한 다음 숫자가 있는지 여부를 판단하는 것은 숫자가 있는 비트가 0 또는 1인지 판단하는 것입니다.
3이 있는지 알고 싶다면 b[0] & (1<<3)만 판단하면 됩니다. 이 값이 0이면 존재하지 않으며 1이면 존재함을 의미합니다.
2. 비트맵의 용도
대용량 데이터의 빠른 정렬, 검색 및 중복 제거
1. 퀵 정렬
0-7 내에서 5개의 요소(4, 7, 2, 5, 3)를 정렬한다고 가정하면(이러한 요소가 반복되지 않는다고 가정) 비트맵 방법을 사용하여 정렬의 목적을 달성할 수 있습니다.
8개의 숫자를 나타내기 위해서는 8Bit(1Bytes)만 있으면 되는데 먼저 1Byte 공간을 열어 이 공간의 모든 Bits를 0으로 설정하고 해당 위치를 1로 설정합니다.
마지막으로 Bit 영역을 1회 통과하여 1인 비트의 수(2, 3, 4, 5, 7)를 출력하여 Sorting의 목적이 이루어지도록 하고, 시간복잡도는 O(n)이다.
이점:
높은 컴퓨팅 효율성, 비교 및 이동이 필요 없음,
N=10000000과 같이 적은 메모리 사용량, N/8=1250000Byte=1.25M 메모리 사용량만
결점:
모든 데이터는 반복할 수 없습니다. 즉, 중복된 데이터는 정렬 및 검색이 불가능합니다.
데이터가 밀집된 경우에만 이점
2. 빠른 중복 제거
20억 개의 정수 중에서 고유한 정수의 수를 찾으십시오. 메모리는 이 20억 개의 정수를 저장하기에 충분하지 않습니다.
우선 "메모리 공간이 이 5억개의 정수를 수용하기에 충분하지 않다"에 따라 Bit-map을 빠르게 연관시킬 수 있습니다. 아래의 핵심 질문은 이러한 20억 개의 숫자 상태를 나타내기 위해 비트맵을 디자인하는 방법입니다. 사실, 이 문제는 매우 간단합니다.숫자는 존재하지 않음, 하나만 있음, 반복의 세 가지 상태 만 있습니다. 따라서 숫자의 상태를 저장하는 데는 2비트만 있으면 되는데, 존재하지 않는 숫자를 00으로 설정하고, 한 번 존재하는 숫자는 01로, 두 번 이상 존재하는 숫자는 11로 설정한다고 가정해 보겠습니다. 그러면 약 2G의 저장 공간이 필요할 것입니다.
다음 작업은 이 20억 개의 숫자를 (저장)에 넣고 해당 상태 비트가 00이면 한 번 존재한다는 의미인 01로 변경하고, 해당 상태 비트가 01이면 11로 변경하여 있음을 나타냅니다. 는 이미 1, 즉 여러 번 나타납니다. 11인 경우 해당 상태 비트는 변경되지 않은 상태로 유지되며 여전히 여러 번 나타남을 나타냅니다.
마지막으로 상태 비트 01의 개수를 세어 반복되지 않는 개수를 구하고, 시간복잡도는 O(n)이다.
3. 빠른 검색
아까도 말했지만 int 배열의 원소는 4바이트이고 32비트를 차지하는데 32로 나누면 원소의 첨자를 알 수 있고 32의 나머지(%32)를 구하면 어느 비트에 있는지 알 수 있다. . 비트가 1이면 현재 있음을 의미합니다.
3. 요약 및 검토
비트맵은 주로 키워드의 상태를 빠르게 검색하기 위해 사용되며, 보통 키워드는 연속적인 순서여야 합니다(또는 키워드는 대부분 연속적인 순서입니다). (2가지 상태)이지만 필요에 따라 2bit(4가지 상태를 나타냄), 3bit(8가지 상태를 나타냄)도 사용할 수 있습니다.
Bitmap의 주요 응용 프로그램: 연속(또는 거의 연속, 즉 대부분이 나타남) 키워드 시퀀스의 상태를 나타냅니다(상태/키워드 수가 적을수록 좋음).
32비트 시스템에서 int a=1과 같은 정수의 경우 컴퓨터 작업의 편의를 위해 메모리에서 32비트를 차지합니다. 그러나 일부 응용 프로그램 시나리오에서는 해당 32비트 비트를 사용하여 10진수 0-31을 저장할 수 있기 때문에 이것은 엄청난 낭비이며 이것이 비트맵의 기본 아이디어입니다. 비트맵 알고리즘은 이 아이디어를 사용하여 대량 데이터의 정렬, 쿼리 및 중복 제거를 처리합니다.
넷, 깨닫다
JDK의 BitSet 컬렉션과 Google의 JavaEWAH 클래스 라이브러리는 모두 BitMap을 구현합니다. 다음 기사를 읽을 수 있습니다. [데이터 구조] BitMap
5. 보충
보충 1
숫자가 넘치지 않는다는 전제하에 양수와 음수의 경우 왼쪽으로 1비트 이동하는 것은 2의 1승과 같고, 왼쪽으로 n비트 이동하는 것은 2의 거듭제곱과 같습니다. , 오른쪽으로 1비트 이동하는 것은 2로 나누는 것과 같고, 오른쪽으로 n비트 이동하는 것은 2의 n승으로 나누는 것과 같습니다.
<< 왼쪽으로 이동, 2의 n제곱을 곱한 것과 같습니다. 예: 1<<6은 1×64=64에 해당하고 3<<4는 3×16=48에 해당합니다.
오른쪽으로 이동하는 것은 2의 n승으로 나누는 것과 같습니다. 예: 64>>3은 64÷8=8과 같습니다.
^ XOR, 나머지를 찾는 것과 같음, 예: 48^32는 48%32=16과 같음
보충 2
타사 변수를 사용하지 않고 두 변수의 값을 교환
// 方式一
a = a + b;
b = a - b;
a = a - b;
// 方式二
a = a ^ b;
b = a ^ b;
a = a ^ b;
참고:
BitMap 소개
【데이터 구조】BitMap
에는 40억 개의 QQ 번호가 있으며 1G 메모리로 제한됩니다. 중복 제거 방법은 무엇입니까?