키(Key)에 데이터 값(Value)을 저장하는 자료구조.
Key를 통해 바로 데이터를 받아오는 것이 가능하며 그래서 속도가 빠르다.
파이썬의 딕셔너리(Dictionary)타입이 해쉬테이블의 대표적인 예시, 따라서 파이썬에서는 해쉬테이블을 따로 구현하지 않아도 된다.
주요 용도 : 데이터의 검색, 저장, 삭제, 읽기가 빈번한 경우 또는 캐쉬 구현(쉬운 중복확인)
<해쉬 테이블 개념도> 출처 : https://dev-kani.tistory.com/1
해쉬(Hash) : 임의 값을 고정 길이로 변환하는 것
해싱 함수(Hash Function) : Key를 해쉬 값(Value)이 저장되는 주소 값으로 바꾸기 위한 수식
해싱(Hashing) : 키(Key) 값을 해시 함수(Hash Function)라는 수식에 대입시켜 계산한 후 나온 결과를 주소로 사용하여 바로 값(Value)에 접근하게 하는 일련의 과정.
해쉬 주소(Hash Address) : key를 해싱 함수로 연산 후, 해쉬 값(Value) 을 알아내고, 이것으로 해쉬 테이블에서 해당 key에 맞는 데이터 위치를 찾음
버킷(bucket) : 여러개의 슬롯을 저장하는 레코드 형태의 자료 구조, 갯수는 고정적
슬롯(Slot) : 한 개의 데이터를 저장할 수 있는 공간, 하나의 버킷 안에는 여러 개의 슬롯이 존재할 수 있음.
서로 다른 두 개의 key가 해쉬 함수에 의해 동일한 해쉬 주소로 변활될 수 있으므로 여러개의 항목을 동일한 버킷, 다른 슬롯에 저장할 수 있다
해쉬 충돌(Hash Collision) : 서로 다른 key값이 동일한 인덱스로 매핑될 경우, 해쉬 충돌이 발생하여 해쉬테이블의 성능을 떨어뜨린다. 버킷 안에는 여러 개의 슬롯이 있어서 충돌이 생겨도 저장은 가능하다
오버플로우(Overflow) : Key가 모든 slot이 꽉 찬 Bucket에 매핑된 경우, 위의 충돌에서 슬롯의 개수는 유한하기 때문에 주어진 슬롯이 가득차서 저장을 하지 못하는 경우를 오버플로우라고 한다.
클러스터(Cluster) : 해쉬 함수가 연산한 해쉬 값들이 골고루 분포하지 않고 레코드(저장공간) 한쪽에 뭉쳐있는 현상
📌 데이터를 적절히 분산하고 충돌을 최소화 하는 좋은 해쉬 함수를 정의하는 것이 중요
Key를 입력받아 해쉬주소를 생성 후 만들어진 주소가 해쉬테이블의 인덱스가 된다.
특징
종류
Division Method : 나눗셈과 나머지 연산자를 이용, 키(입력값)를 해쉬테이블의 크기로 나눈 나머지를 해시값으로 반환한다.
키 값 % 전체 테이블의 크기 = 인덱스
해쉬 주소가 고르게 분포하기 위해 테이블의 크기를 소수(Prime number)를 사용하고 2의 제곱수와 먼 값을 사용하는 것이 좋다.
Digit Folding : key를 마지막 부분을 제외하고 동일하게 분할한 후 각 부분을 모두 더하거나 XOR연산 하는 등의 연산을 하여 테이블 내의 주소(Index)로 사용하는 방법.
key가 문자열일 경우 ASCII코드로 바꿔서 연산함.
Multiplication Method : 숫자로 된 key값이 k이고 A는 0과 1사이의 실수일 때, 보통 2의 제곱수인 m을 사용하여 다음과 같은 계산을 해준다.
나눗셈법 보다는 다소 느림, 2진수 연산에 최적화된 컴퓨터 구조를 고려한 함수
h(k)=(kA % 1) × m
Radix Conversion : 진수 변환을 통해 테이블 내의 주소로 사용하는 방법.
Algebraic Coding : key를 이루고 있는 각각의 bit를 다항식의 계수로 이용하여 계산한 값을 테이블 내의 주소로 사용하는 방법.
Univeral Hashing : 다수의 해시함수를 만들고 이 해시함수의 집합 H에서 무작위로 해시함수를 선택해 해시값을 만드는 기법.
📌 대표적으로 쓰이는 알고리즘 예시
MD5(message digest 5)
SHA(Secure Hash Algorithm)
이미지 출처 : http://wiki.hash.kr/index.php/SHA
해쉬함수의 입력 값은 무한하지만 출력 값의 가짓수는 유한하므로 해쉬충돌의 발생은 필연적이다. 그러나 너무 많은 해쉬 충돌은 해쉬 테이블의 성능을 떨어뜨린다.
체이닝(Chaining)
John과 Sandra는 같은 해시 값(152)으로 매핑되고 있다.
개방 주소법 (Open Addressing)
한 bucket당 들어갈 수 있는 엔트리가 하나뿐인 해쉬 테이블.
해쉬 함수로 얻은 주소가 아닌, 비어있는 공간을 활용해서 다른 주소에 데이터를 저장.
추가적인 메모리를 사용하지 않아 메모리 문제가 발생하지 않으나 충돌발생 가능.
1. 선형 탐사(Linear Probing)
2. 제곱 탐사(Quadratic Probing)
3. 이중 해싱 (double hashing)
Chaining :
Open Addressing :
https://colinch4.github.io/2021-01-14/DataStructure_HashTable/
https://dev-kani.tistory.com/2
https://j3sung.tistory.com/759
https://ratsgo.github.io/data%20structure&algorithm/2017/10/25/hash/
https://medium.com/depayse/kotlin-data-structure-hashtable-ebb9f949e936
http://wiki.hash.kr/index.php/%ED%95%B4%EC%8B%9C%EC%B6%A9%EB%8F%8C