임의의 길이의 데이터(Key)를 해시함수를 통해 매핑된 고유의 데이터
key → 함수 → 해시
key 데이터를 고유한 데이터로 바꿔주는 함수
key와 hash 검색과 삭제가 O(1)의 시간복잡도를 갖게된다
데이터가 많아지다보면 서로 다른 key가 같은 해시값을 갖는데 이를 충돌이라고 한다
해시함수를 사용하여 key 해시값으로 매핑하고 해시값을 index 삼아 bucket에 값을 함께 저장하는 자료구조(reference를 저장하여 entry 생성)
Key → hash function → Hash → Bucket(value)
해시테이블은 해시 충돌이 일어나지 않는다는 가정하에 삽입, 삭제, 검색에 O(1)의 시간복잡도를 가지고
충돌이 일어나면 최악의 경우 O(n)의 시간 복잡도를 갖는다
해시테이블은 충돌을 막기위해 다양한 알고리즘을 해시 테이블에 적용하여 충돌을 피한다.
크게 두가지로 볼 수 있는데 체이닝, 직접주소개방
어떤 해시 충돌 알고리즘을 사용하냐에 따라 삽입연산 구현방법과 삭제연산도 맞게 구현해야한다
체이닝 방법은 동일한 해시 값을 갖는 key를 다른 버킷에 넣는 것이 아니라 동일한 버킷에 연결리스트 형식으로 연결하는 방법이다.
가장 간단하지만 하나의 해시값에 여러 엔트리가 몰릴수 있다.
그렇게 되면 리스트처럼 선형구조를 갖는 것이라 최악의 경우 하나의 데이터를 찾는데 최대한 빠른시간이 아닌 O(n)의 시간복잡도를 가질 수 있음.
→ 해시테이블의 장점이 퇴색됨
해시충돌 발생시 다른 보조함수를 이용하여 빈버킷의 공간을 찾아 데이터를 저장하는 방식
bucket과 entry가 항상 1:1 대응 관계를 유지할 수 있어 빠른 탐색의 장점을 갖는다
해시함수의 결과에 Mod(나머지 연산)을 적용하여 bucket의 크기보다 index가 커지는 것을 방지
bucket의 크기도 소수로 해야 함수의 반환값이 편향되어도 mod 잏의 값이 고르게 분포된어 충돌 가능성을 낮춘다
한계
→ 보조 해시 함수에 따라 선형조사법, 이차조사법, 이중해싱법 세가지로 나뉜다
선형 조사법의 보조함수는 충돌 발생시 기존 해시값에 +1을 더하는 함수
충돌이 발생하지 않을때까지 +1을 반복하여 저장한다. 단, 충돌한 데이터와 같은 hash 값을 갖는다.
충돌 시: bucket의 크기는 7, key값 8에 대해 해시 값 10(h(8) = 10)이라고 가정
한계
해시 충돌이 한곳으로 집중되어 해당 index를 중심으로 군집화가 발생하면 처음 해시값을 찾아 하나씩 index를 더해가면서 찾아야 해서 결과적으로 배열과 유사한 구조를 갖게되어 빠른 탐색의 장점이 사라진다.
선형조사가 갖는 군집화를 해결하고자 나타난 방법.
+1이 아닌 상수 제곱 값을 더하여 군집화를 방지
충돌 시: bucket의 크기는 7, key값 8에 대해 해시 값 10(h(8) = 10)이라고 가정
한계
두가지 보조 해시함수를 적용하여 군집화를 해결하고 값이 커지면서 공간을 못찾는 문제 해결
한계: 추가 연산이 있어 함수의 성능이 테이블 성능에 영향을 미칠 수 있다.
일반적으로 해시값에 대응된 bucket으로 접근하지만
충돌이 있는경우 알고리즘 규칙에 따라서 해시값이 동일한 bucket 중 찾고자 하는 key를 저장한 entry를 찾아 bucket을 탐색한다.
이때 Null값이 있다면 해당key에 해시테이블이 없으므로 탐색을 종료
chaining의 경우 리스트 규칙에 따라
직접 개방 주소의 경우 보조 해시함수를 규칙에 따라
→ 이때문에 O(n)까지 증가 할수 있다
탐색 연산과 거의 같다. 해당값을 탐색하고 Null 값으로 만들면됨
삭제하는 것이 아니라 충돌 해결 알고리즘에 맞게 bucket의 저장된 값을 적절하게 재배치하는 것
bucket을 지워버리면 탐색을 할 수 없는 자료구조가 되어버림
체이닝
chaining의 경우 연결리스트 방식에 따라 삭제하면된다.(중복된 해시값에 저장하지 않았기때문)
선형 조사법
군집화로 인해 하나의 해시에 여러 데이터가 묶여있을수 있기떄문에
Null값이 저장된 인덱스로 해당값을 재배치해서 앞데이터와 뒤데이터를 이어줘야한다.
Reference