[Algorithm] 비트마스크
- Computer Science/Algorithm
- 2017. 4. 14. 13:53
반응형
비트마스크는 정수의 이진수 표현을 자료 구조로 쓰는 기법입니다. 비트마스크를 사용하는 코드는 다음과 같은 장점이 있죠.
1. 더 빠른 수행 시간 : 보통 O(1)에 실행됨
2. 더 간결한 코드 : 복잡한 코드를 한 줄에 작성 가능
3. 더 적은 메모리 사용량 : 예시로, 32개의 아이템의 유무를 나타내는 배열을 32bit 자료형으로 대체 가능
4. 연관 배열을 배열로 대체 : c++ 경우, map<vector<bool>, int>를 사용한다고 하면 이를 단순 int[] 배열로 대체 가능
만일 비트마스크로 코드를 작성 시, c++이나 java같은 자료형의 데이터 범위가 정해져 있는 언어에서는 오버플로우나 언더플로우에 주의해야합니다.
bool is_bit_set(unsigned long long a, int b){ return ( a & ( 1<< b) ) > 0; }
a를 이루고 있는 64bit 셋의 b번째 bit가 켜져있는 지 꺼져있는 지 확인하는 함수입니다. 하지만 여기서 주의할 것은 기본적으로 c++에서는 1은 부호있는 32bit 상수로 취급하기 때문에 위의 경우처럼 작성 할 때, b>=32 이상일 시 오버플로우가 일어나게 됩니다. 이 때는 1에다가 64bit라는 표현으로 1ULL이라든 지 (long long)을 붙여야 합니다. 그리고 자잘한 버그를 피하고 싶다면 unsigned형을 쓰시는 것이 좋습니다.
다음은 비트마스크로 할 수 있는 연산들을 모아 봤습니다.
공집합
0으로 표현
n개의 꽉 찬 집합
int set = (1 << n) - 1;원소 추가
set |= (1 << n);원소 포함 여부
return set & (1 << n);
원소의 삭제
set &= ~(1<<n);
원소의 토글
set ^= (1<<n)
두 집합의 연산
int added = (a | b); int intersection = ( a & b); int removed = (a & ~b); int toggled = (a ^ b);
집합의 크기
int bit_count(int set){ if( set == 0) return 0; return x % 2 + bit_count( set / 2 ); }빌트인 함수로도 찾을 수 있습니다.
gcc/g++ -> __builtin_popcount(set)
Visual C++ -> __popcnt(set)
최소 원소 찾기
빌트인 함수로 찾을 수 있습니다.
gcc/g++ -> __builtin_ctz(set)
Visual C++ -> _BitScanForward(&index, set)
최하위 비트
int first_pop = (set & -set);
최소 원소 지우기
set &= (set -1);
모든 집합 순회
for(int subset = set; subset; subset = (subset - 1) & set) ){ //code }
크기가 N인 집합의 모든 부분 집합을 순회하고 싶다면
pre class="brush:cpp;">for(int subset = 0; subset < (1 << n); subset++ ){ //code }참고 : 알고리즘 문제해결 전략 2권
반응형
'Computer Science > Algorithm' 카테고리의 다른 글
[Algorithm]Floyd-Warshall(플로이드-워샬 알고리즘) (0) | 2017.10.17 |
---|---|
[Algorithm] Bellman-Ford(벨만포드) (2) | 2017.10.09 |
[Algorithm] LCS(Longest Common Subsequence) (0) | 2017.10.06 |
[Algorithm] 네트워크 유량(Network Flow) (0) | 2017.10.01 |
[Algorithm] 소수 구하기 (0) | 2017.04.15 |
이 글을 공유하기