1. 해시의 정의와 필요성
1.1 해시란?
- 정의: 검색과 저장이 아주 빠르게 진행되는 데이터를 다루는 기법
- 특징:
- Key -> Value를 이용한 빠른 탐색
- key와 value가 한 쌍으로 존재
- key값이 배열(해쉬테이블)의 인덱스로 변환
- 검색과 저장의 평균적 시간 복잡도가 O(1)
1.2 해시의 주요 구성 요소
- Key: 검색할 때 사용하는 인풋
- Value: 검색해서 찾아내는 아웃풋
- Hash function: 탐색할 data를 해시값으로 변환하는 함수
- Hash Table: 해시 함수에 의해 반환된 주소의 위치에 항목을 저장한 자료 구조
2. 해시 구현
2.1 Hash Key
- 구현 방식:
- 고유한 값으로 해시 함수에 입력 값으로 사용
- 키 값 그대로 최종 저장소에 저장되면 다양한 길이의 저장소를 미리 구성해야 함
- 해쉬 함수로 값을 바꿔 저장
2.2 Hash Value
- 구현 방식:
- 최종 저장소 (aka bucket, slot)에 hash와 매칭되어 저장
2.3 Hash Collision
- 정의: 서로 다른 Key인데, 해시 값이 같게 나오는 경우
- 해결 방법:
- Chaining:
- 충돌나는 값을 기존 값과 연결시켜 저장
- key:value 매칭이 1:N
- 연결 시키는 방법: Linked List
- 검색 효율이 떨어질 수 있지만, 저장소를 효율적으로 사용하여 메모리를 적게 쓰는 장점
- Open Addressing:
- 충돌이 발생하면 다른 비어있는 자리에 저장
- key:value 매칭을 1:1로 유지
- 비어있는 자리 찾는 방법:
- 선형 탐색(Linear Probing): 다음 해시(+1)나 n개(+n)을 건너뛰어 빈자리 찾기
- 제곱 탐색 (Qudratic Probing): 충돌이 일어난 해시의 제곱을 한 해시에 데이터를 저장
- 이중 해시(Double Hasing): 다른 해시함수를 한 번 더 적용한 해시에 데이터를 저장
3. 해시 테이블 크기
3.1 크기 선택 기준
- 권장 크기:
- 보통 소수 (prime number)나 2^N 사이즈를 사용
- 흔히 쓰이는 소수: 10007, 20011, 30011, 40009, 100003, 200003
- C++의 Unordered Associative Containers는 소수를 사용
3.2 크기 선택 시 고려사항
- 소수 사용의 장점:
- 해시 함수가 아주 고르게 분포하는 값들을 출력해주면 테이블 크기가 소수가 아니어도 괜찮음
- 특정 자리(예 5의 배수)에 몰리는 상황도 발생할 수 있음
- 가장 이상적인 테이블의 크기는 자신을 제외한 모든 수와 서로소인 소수
- 2의 거듭제곱 사용의 단점:
- bit masking을 통해 나머지를 빠르게 계산할 수 있음
- m개의 하위 bit를 그대로 사용하기 때문에 해쉬 함수가 하위 bit을 고르게 분포 시키지 못하면 많은 충돌이 발생
3.3 생일 문제와 해시 테이블 크기
- 생일 문제 예시:
- 366명 이상의 사람이 모이면 생일이 같은 사람이 반드시 한 쌍 이상 나옴
- 생일이 같은 쌍이 존재할 확률이 50%가 되기 위해서는 23명이 필요
- 23개의 데이터를 삽입했을 때 충돌이 일어날 확률을 50%로 유지하는데만 해도 365개 크기의 테이블이 필요
- 충돌 방지를 위해 단순 테이블 크기를 늘리는 것은 좋은 방법이 아님
4. 해시 구현 예시
4.1 Java 구현
// 기본
HashMap<String, Integer> testMap = new HashMap<String, Integer>();
testMap.put("s",2);
testMap.put("s",1); // 중복이라 덮어씌움
testMap.put("s1",2);
testMap.putIfAbsent("s1",3); // 중복 key가 입력되었을 때 업데이트 x
System.out.println(testMap.get("s")); // 1
System.out.println(testMap); // {s=1, s1=2}
// 기타 해쉬 메서드
remove()
clear()
replace(K key, V new_value)
size()
contains()
getOrDefault(Object k, V defaultValue)
댓글남기기