비트맵 데이터 구조

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 메모리로 제한됩니다. 중복 제거 방법은 무엇입니까?

Guess you like

Origin blog.csdn.net/qq_33697094/article/details/130987801