해시 테이블
| 해시 테이블 | ||||||||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| 종류 | 정렬되지 않은 연관 배열 | |||||||||||||||||||||||
| 발명일 | 1953 | |||||||||||||||||||||||
| ||||||||||||||||||||||||

컴퓨터 과학에서 해시 테이블(hash table)은 딕셔너리(dictionary) 또는 단순히 맵(map)이라고도 불리는 연관 배열을 구현하는 자료 구조이다. 연관 배열은 유일 키를 값에 매핑하는 추상 자료형이다.[3] 해시 테이블은 해시 함수를 사용하여 버킷 또는 슬롯의 배열로 인덱스(해시 코드라고도 함)를 계산하고, 여기서 원하는 값을 찾을 수 있다. 조회 중에 키는 해시되고 결과 해시는 해당 값이 저장된 위치를 나타낸다. 해시 테이블로 구현된 맵을 해시 맵이라고 한다.
대부분의 해시 테이블 설계는 불완벽 해시 함수를 사용한다. 따라서 해시 함수가 하나 이상의 키에 대해 동일한 인덱스를 생성하는 해시 충돌은 일반적으로 어떤 방식으로든 처리되어야 한다. 해시 충돌을 처리하는 일반적인 전략에는 연결 리스트를 사용하여 동일한 슬롯에 여러 요소를 저장하는 체이닝과 프로빙 시퀀스에 따라 다음 사용 가능한 슬롯을 검색하는 개방 주소 지정이 있다.[4]
잘 구성된 해시 테이블에서 각 조회의 평균 시간 복잡도는 테이블에 저장된 요소 수와 독립적이다. 많은 해시 테이블 설계는 키-값 쌍의 임의 삽입 및 삭제를 허용하며, 작업당 분할 상환 상수에 평균 비용을 가진다.[5][4]: 513–558 [6]
해싱은 공간-시간 트레이드오프의 예시이다. 메모리가 무한하다면, 전체 키를 직접 인덱스로 사용하여 단일 메모리 접근으로 값을 찾을 수 있다. 반대로, 무한한 시간을 사용할 수 있다면, 값은 키에 관계없이 저장될 수 있으며, 요소를 검색하기 위해 이진 검색 또는 선형 검색이 사용될 수 있다.[7]: 458
많은 상황에서 해시 테이블은 탐색 트리 또는 다른 테이블 조회 구조보다 평균적으로 더 효율적인 것으로 밝혀졌다. 해시 테이블은 빠른 평균 사례 성능 때문에 데이터베이스 인덱싱, 캐싱 및 연관 배열 구현과 같은 작업에 현대 소프트웨어 시스템에서 널리 사용된다.[8] 이러한 이유로, 특히 연관 배열, 데이터베이스 인덱싱, 캐시, 집합과 같은 다양한 종류의 소프트웨어에서 널리 사용된다. 많은 프로그래밍 언어는 프로그래머로부터 해싱의 복잡성을 추상화하는 Python의 딕셔너리, Java의 HashMap, C++의 unordered_map과 같은 내장 해시 테이블 구조를 제공한다.[9]
역사
[편집]해싱의 개념은 여러 곳에서 독립적으로 발생했다. 1953년 1월, 한스 페터 룬은 체이닝을 사용하는 내부 IBM 메모랜덤을 작성했다. 개방 주소 지정의 첫 번째 예시는 룬의 메모랜덤을 기반으로 A. D. 린에 의해 제안되었다.[4]: 547 거의 같은 시기에 진 암달, 일레인 M. 맥그로, 너새니얼 로체스터, 아서 새뮤얼은 IBM 리서치에서 IBM 701 어셈블러에 해싱을 구현했다.[10]: 124 선형 프로빙을 사용하는 개방 주소 지정은 암달에게 공로가 있지만, 안드레이 예르쇼프도 독립적으로 같은 아이디어를 가지고 있었다.[10]: 124–125 "개방 주소 지정"이라는 용어는 W. 웨슬리 피터슨이 대용량 파일 검색 문제에 대해 논의한 기사에서 만들어졌다.[11]: 15
체이닝을 이용한 해싱에 대한 첫 번째 출판물은 프라임 모듈로 나머지를 해시 함수로 사용하는 아이디어를 논의한 아놀드 듀미에게 공로가 있다.[11]: 15 "해싱"이라는 단어는 로버트 모리스의 기사에서 처음 출판되었다.[10]: 126 선형 프로빙의 이론적 분석은 원래 콘하임과 바이스가 제출했다.[11]: 15
개요
[편집]연관 배열은 (키, 값) 쌍의 집합을 저장하고 삽입, 삭제 및 조회(검색)를 허용하며, 유일 키의 제약이 있다. 연관 배열의 해시 테이블 구현에서 길이 인 배열 는 개의 요소로 부분적으로 채워지며, 여기서 이다. 키 는 해시 함수 를 사용하여 해시되어 해시 테이블 내의 인덱스 위치 를 계산하며, 여기서 이다. 해시 테이블의 효율성은 로드 팩터에 따라 달라지는데, 이는 저장된 요소 수와 사용 가능한 슬롯 수의 비율로 정의되며, 로드 팩터가 낮을수록 일반적으로 작업이 빨라진다.[12] 이 인덱스에 키와 그에 연결된 값이 모두 저장된다. 값을 키와 함께 저장하면 조회 시 인덱스의 키를 확인하여 충돌이 발생하더라도 올바른 값을 검색할 수 있다. 합리적인 가정 하에 해시 테이블은 자가 균형 이진 탐색 트리에 비해 검색, 삭제 및 삽입 작업에 대한 더 나은 시간 복잡도 한계를 가진다.[11]: 1
해시 테이블은 또한 각 키에 대해 저장된 값을 생략하고 키의 존재 여부만 추적하여 집합을 구현하는 데 일반적으로 사용된다.[11]: 1
로드 팩터
[편집]로드 팩터 는 해시 테이블의 중요한 통계이며 다음과 같이 정의된다.[2] 여기서
- 은 해시 테이블에 채워진 엔트리의 수이다.
- 은 버킷의 수이다.
해시 테이블의 성능은 로드 팩터 에 비례하여 저하된다.[11]: 2 과 이 큰 극한에서는 이상적인 무작위 해시 함수에 대해 각 버킷은 통계적으로 기대값 를 가진 푸아송 분포를 따른다.
소프트웨어는 일반적으로 로드 팩터 가 특정 상수 미만으로 유지되도록 보장한다. 이는 좋은 성능을 유지하는 데 도움이 된다. 따라서 일반적인 접근 방식은 로드 팩터 가 에 도달할 때마다 해시 테이블의 크기를 조정하거나 "재해싱"하는 것이다. 마찬가지로 로드 팩터가 아래로 떨어지면 테이블 크기를 조정할 수도 있다.[13]
분리 체이닝의 로드 팩터
[편집]분리 체이닝 해시 테이블에서 버킷 배열의 각 슬롯은 데이터의 연결 리스트 또는 배열에 대한 포인터를 저장한다.[14]
분리 체이닝 해시 테이블은 로드 팩터가 증가함에 따라 성능이 점진적으로 저하되며, 재조정이 절대적으로 필요한 고정 지점은 없다.[13]
분리 체이닝에서 최상의 성능을 제공하는 값은 일반적으로 1에서 3 사이이다.[13]
개방 주소 지정의 로드 팩터
[편집]개방 주소 지정에서는 버킷 배열의 각 슬롯이 정확히 하나의 항목을 보유한다. 따라서 개방 주소 지정 해시 테이블은 로드 팩터가 1보다 클 수 없다.[14]
개방 주소 지정의 성능은 로드 팩터가 1에 가까워지면 매우 나빠진다.[13]
따라서 개방 주소 지정을 사용하는 해시 테이블은 로드 팩터 가 1에 가까워지면 크기를 조정하거나 재해싱해야 한다.[13]
개방 주소 지정에서 허용 가능한 최대 로드 팩터 는 약 0.6에서 0.75 범위여야 한다.[15][16]: 110
해시 함수
[편집]해시 함수 는 키의 유니버스 를 테이블 내의 인덱스 또는 슬롯에 매핑한다. 즉, 에 대해 이다. 해시 함수의 일반적인 구현은 테이블의 모든 요소가 워드 크기 내에 의 비트 길이가 제한되는 유니버스 에서 파생된다는 정수 유니버스 가정에 기반한다.[11]: 2
해시 함수 는 주어진 집합 에 대해 단사적이면, 즉 의 각 요소 가 에서 다른 값으로 매핑되면 완벽하다고 한다.[17][18] 모든 키를 미리 알고 있다면 완벽 해시 함수를 만들 수 있다.[17]
정수 유니버스 가정
[편집]정수 유니버스 가정에 사용되는 해싱 방식은 나눗셈 해싱, 곱셈 해싱, 유니버설 해싱, 동적 완벽 해싱 및 정적 완벽 해싱을 포함한다.[11]: 2 그러나 나눗셈 해싱은 일반적으로 사용되는 방식이다.[19]: 264 [16]: 110
나눗셈 해싱
[편집]나눗셈 해싱의 방식은 다음과 같다.[11]: 2 여기서 는 의 해시 값이고 은 테이블의 크기이다.
곱셈 해싱
[편집]곱셈 해싱의 방식은 다음과 같다.[11]: 2–3 여기서 는 정수가 아닌 실수 상수이고 은 테이블의 크기이다. 곱셈 해싱의 장점은 이 중요하지 않다는 것이다.[11]: 2–3 어떤 값도 해시 함수를 생성하지만, 도널드 커누스는 황금비를 사용할 것을 제안한다.[11]: 3
문자열 해싱
[편집]일반적으로 문자열이 해시 함수의 키로 사용된다. 스트롭스트루프[20]는 처음에 0인 부호 없는 정수를 반복적으로 1비트 왼쪽 시프트한 다음 다음 문자의 정수 값과 XOR 연산하는 간단한 해시 함수를 설명한다. 이 해시 값은 테이블 크기의 모듈로 취해진다. 왼쪽 시프트가 순환 시프트가 아닌 경우 문자열 길이는 부호 없는 정수의 비트 크기보다 최소 8비트 작아야 한다. 문자열을 정수로 해시하는 또 다른 일반적인 방법은 다항식 롤링 해시 함수를 사용하는 것이다.
해시 함수 선택
[편집]해시 값의 균등 분포는 해시 함수의 근본적인 요구 사항이다. 균등하지 않은 분포는 충돌 횟수와 이를 해결하는 비용을 증가시킨다. 균등성은 설계상 보장하기 어려운 경우가 있지만, 피어슨 카이제곱 검정과 같은 통계적 테스트를 사용하여 경험적으로 평가할 수 있다.[21][22]
분포는 애플리케이션에서 발생하는 테이블 크기에 대해서만 균일해야 한다. 특히 테이블 크기를 정확히 두 배로 늘리고 반으로 줄이는 동적 크기 조정을 사용하는 경우 해시 함수는 크기가 2의 거듭제곱일 때만 균일해야 한다. 여기서 인덱스는 해시 함수의 일부 비트 범위로 계산될 수 있다. 반면에 일부 해싱 알고리즘은 크기가 소수인 것을 선호한다.[23]
개방 주소 지정 방식의 경우 해시 함수는 클러스터링도 피해야 한다. 클러스터링은 둘 이상의 키를 연속적인 슬롯에 매핑하는 것이다. 이러한 클러스터링은 로드 팩터가 낮고 충돌이 드물더라도 조회 비용을 급등시킬 수 있다. 널리 사용되는 곱셈 해시(multiplicative hash)는 특히 클러스터링 동작이 좋지 않은 것으로 알려져 있다.[23][4]
K-독립 해싱은 주어진 해시 테이블 유형에 대해 특정 해시 함수에 나쁜 키 집합이 없음을 증명하는 방법을 제공한다. 선형 프로빙 및 쿠쿠 해싱과 같은 충돌 해결 방식에 대해 K-독립성 결과가 다수 알려져 있다. K-독립성은 해시 함수가 작동함을 증명할 수 있으므로, 가장 빠른 해시 함수를 찾는 데 집중할 수 있다.[24]
충돌 해결
[편집]해싱을 사용하는 검색 알고리즘은 두 부분으로 구성된다. 첫 번째 부분은 검색 키를 배열 인덱스로 변환하는 해시 함수를 계산하는 것이다. 이상적인 경우는 두 검색 키가 동일한 배열 인덱스로 해시되지 않는 것이다. 그러나 이는 항상 그런 것은 아니며 보이지 않는 데이터에 대해 보장할 수 없다.[4]: 515 따라서 알고리즘의 두 번째 부분은 충돌 해결이다. 충돌 해결을 위한 두 가지 일반적인 방법은 분리 체이닝과 개방 주소 지정이다.[7]: 458
분리 체이닝
[편집]

분리 체이닝에서는 각 검색 배열 인덱스에 대해 연결 리스트를 이름-값 쌍으로 구성하는 과정이 포함된다. 충돌된 항목은 단일 연결 리스트를 통해 함께 연결되며, 고유한 검색 키로 항목에 접근하기 위해 리스트를 순회할 수 있다.[7]: 464 연결 리스트를 사용한 체이닝을 통한 충돌 해결은 해시 테이블 구현의 일반적인 방법이다. 를 해시 테이블, 를 노드라고 하면, 작업은 다음과 같이 수행된다.[19]: 258
Chained-Hash-Insert(T, k) insert x at the head of linked list T[h(k)]
Chained-Hash-Search(T, k) search for an element with key k in linked list T[h(k)]
Chained-Hash-Delete(T, k) delete x from the linked list T[h(k)]
요소가 수치적으로든 사전적으로든 비교 가능하고 전순서를 유지하며 리스트에 삽입되면, 실패한 검색의 종료가 빨라진다.[4]: 520–521
분리 체이닝을 위한 다른 자료 구조
[편집]키가 정렬되어 있는 경우, 자가 균형 이진 탐색 트리와 같은 "자가 구성" 개념을 사용하는 것이 효율적일 수 있으며, 이를 통해 이론적 최악의 경우가 로 줄어들 수 있지만, 추가적인 복잡성이 도입된다.[4]: 521
동적 완벽 해싱에서는 조회 복잡도를 최악의 경우에도 로 보장하기 위해 2단계 해시 테이블이 사용된다. 이 기술에서는 개의 엔트리로 구성된 버킷이 개의 슬롯을 가진 완벽 해시 테이블로 조직되어 상수 시간의 최악의 경우 조회 시간과 낮은 분할 상환 삽입 시간을 제공한다.[25] 한 연구에 따르면 배열 기반 분리 체이닝은 부하가 높을 때 표준 연결 리스트 방법보다 97% 더 나은 성능을 보인다.[26]: 99
각 버킷에 퓨전 트리를 사용하는 것과 같은 기술은 높은 확률로 모든 연산에 대해 상수 시간을 제공한다.[27]
캐싱 및 참조 국부성
[편집]분리 체이닝 구현의 연결 리스트는 공간 국부성—참조 국부성—으로 인해 캐시 인식적이지 않을 수 있다. 연결 리스트의 노드가 메모리에 흩어져 있으면 삽입 및 검색 중 리스트 순회가 CPU 캐시 비효율성을 초래할 수 있기 때문이다.[26]: 91
분리 체이닝을 통한 충돌 해결의 캐시 인식 변형에서는 연결 리스트나 자가 균형 이진 탐색 트리가 일반적으로 배포되는 대신 동적 배열이 사용된다. 이 배열은 캐시 친화적인 것으로 밝혀졌다. 이는 배열의 연속 할당 패턴이 하드웨어 캐시 선인출기—예를 들어 변환 색인 버퍼—에 의해 활용될 수 있어 접근 시간과 메모리 소비가 줄어들기 때문이다.[28][29][30]
개방 주소 지정
[편집]

개방 주소 지정은 모든 엔트리 레코드가 버킷 배열 자체에 저장되고 해시 해결이 프로빙을 통해 수행되는 또 다른 충돌 해결 기술이다. 새 엔트리를 삽입해야 할 때, 해시된 슬롯부터 시작하여 일부 탐사 시퀀스에 따라 버킷을 검사하여 비어 있는 슬롯을 찾는다. 엔트리를 검색할 때, 동일한 시퀀스로 버킷을 스캔하여 대상 레코드를 찾거나 사용되지 않는 배열 슬롯을 찾을 때까지 스캔하며, 이는 검색 실패를 나타낸다.[31]
잘 알려진 탐사 시퀀스는 다음과 같다.
- 선형 탐사, 탐사 간격이 고정되어 있다 (일반적으로 1).[32]
- 제곱 탐사, 탐사 간격이 원래 해시 계산으로 주어진 값에 이차 다항식의 연속적인 출력을 더하여 증가된다.[33]: 272
- 이중 해시, 탐사 간격이 보조 해시 함수에 의해 계산된다.[33]: 272–273
개방 주소 지정의 성능은 로드 팩터 가 1에 가까워질 때 탐사 시퀀스가 증가하므로 분리 체이닝에 비해 느릴 수 있다.[13][26]: 93 테이블이 완전히 채워진 경우 로드 팩터가 1에 도달하면 탐사는 무한 루프로 이어진다.[7]: 471 선형 탐사의 평균 비용은 해시 함수가 요소를 테이블 전체에 균일하게 분산시켜 클러스터링을 피하는 능력에 달려 있다. 클러스터가 형성되면 검색 시간이 증가하기 때문이다.[7]: 472
캐싱 및 참조 국부성
[편집]슬롯이 연속적인 위치에 있기 때문에 선형 프로빙은 참조 국부성으로 인해 CPU 캐시를 더 잘 활용하여 메모리 레이턴시를 줄일 수 있다.[32]
개방 주소 지정 기반의 다른 충돌 해결 기법
[편집]병합 해싱
[편집]병합 해싱은 테이블 내에서 버킷 또는 노드가 연결되는 분리 체이닝과 개방 주소 지정의 하이브리드이다.[34]: 6–8 이 알고리즘은 고정 메모리 할당에 이상적으로 적합하다.[34]: 4 병합 해싱에서 충돌은 해시 테이블에서 가장 큰 인덱스를 가진 빈 슬롯을 식별한 다음, 충돌하는 값을 해당 슬롯에 삽입하여 해결된다. 버킷은 또한 삽입된 노드의 슬롯에 연결되어 충돌하는 해시 주소를 포함한다.[34]: 8
쿠쿠 해싱
[편집]쿠쿠 해싱은 최악의 경우 조회 복잡도와 삽입에 대한 상수 분할 상환 시간을 보장하는 개방 주소 지정 충돌 해결 기술의 한 형태이다. 충돌은 각각 자체 해싱 함수를 가진 두 개의 해시 테이블을 유지함으로써 해결되며, 충돌된 슬롯은 주어진 항목으로 대체되고, 슬롯의 미리 점유된 요소는 다른 해시 테이블로 이동된다. 이 과정은 모든 키가 테이블의 빈 버킷에 자신만의 자리를 가질 때까지 계속된다. 만약 이 절차가 무한 루프에 들어가면(이는 임계 루프 카운터를 유지함으로써 식별된다), 두 해시 테이블 모두 새로운 해시 함수로 다시 해시되고 절차는 계속된다.[35]: 124–125
홉스카치 해싱
[편집]홉스카치 해싱은 쿠쿠 해싱, 선형 탐사 및 버킷의 이웃 개념(주어진 점유된 버킷 주위의 후속 버킷, "가상" 버킷이라고도 함)을 통해 체이닝의 요소를 결합한 개방 주소 지정 기반 알고리즘이다.[36]: 351–352 이 알고리즘은 해시 테이블의 로드 팩터가 90%를 초과할 때 더 나은 성능을 제공하도록 설계되었으며, 병행 환경에서도 높은 처리량을 제공하여 크기 조정 가능한 병행 해시 테이블 구현에 매우 적합하다.[36]: 350 홉스카치 해싱의 이웃 특성은 주어진 이웃 내의 버킷에서 원하는 항목을 찾는 비용이 버킷 자체에서 찾는 비용과 매우 가깝다는 속성을 보장한다. 이 알고리즘은 다른 항목을 이동시키는 가능한 비용을 포함하여 항목을 이웃에 삽입하려고 시도한다.[36]: 352
해시 테이블 내의 각 버킷에는 H 비트 비트 배열인 추가 "홉 정보"가 포함되어 있으며, H - 1 엔트리 내에서 현재 가상 버킷에 원래 해시된 항목의 상대 거리를 나타낸다.[36]: 352 삽입될 키를 , 키가 해시되는 버킷을 라고 하면, 알고리즘의 이웃 속성을 보장하기 위해 삽입 절차에 여러 경우가 포함된다.[36]: 352–353 만약 가 비어 있다면, 요소가 삽입되고 비트맵의 가장 왼쪽 비트가 1로 설정된다. 비어 있지 않다면, 테이블에서 빈 슬롯을 찾기 위해 선형 탐사가 사용되며, 버킷의 비트맵이 업데이트된 후 삽입이 이루어진다. 만약 빈 슬롯이 이웃 범위, 즉 H - 1 내에 없다면, 각 버킷의 이웃 불변 속성에 따라 후속 스왑 및 홉 정보 비트 배열 조작이 수행된다.[36]: 353
로빈 후드 해싱
[편집]로빈 후드 해싱은 개방 주소 지정 기반 충돌 해결 알고리즘이다. 충돌은 "홈 위치" 즉, 항목이 해시된 버킷에서 가장 멀리 떨어져 있거나 가장 긴 탐사 시퀀스 길이(PSL)를 가진 요소를 이동시키는 방식으로 해결된다.[37]: 12 이 이름은 부자에게서 훔쳐 가난한 자에게 주었던 전설적인 로빈 후드 의적의 이름을 따서 명명되었다.
로빈 후드 해싱은 이론적 검색 비용을 변경하지 않지만, 버킷에 있는 항목의 분포의 분산에 크게 영향을 미친다.[38]: 2 즉, 해시 테이블의 클러스터 형성을 처리한다.[39] 로빈 후드 해싱을 사용하는 해시 테이블 내의 각 노드는 추가 PSL 값을 저장하도록 확장되어야 한다.[40] 삽입될 키를 , 을 의 (증가) PSL 길이, 를 해시 테이블, 를 인덱스라고 할 때, 삽입 절차는 다음과 같다.[37]: 12–13 [41]: 5
- If : 외부 탐사를 시도하지 않고 다음 버킷으로 이동한다.
- If : 항목 를 버킷 에 삽입하고, 와 를 교환한다—이를 라고 하자. 번째 버킷에서 를 삽입하기 위한 탐사를 계속한다. 모든 요소가 삽입될 때까지 이 절차를 반복한다.
동적 크기 조정
[편집]반복된 삽입은 해시 테이블의 엔트리 수를 증가시키고, 결과적으로 로드 팩터를 증가시킨다. 조회 및 삽입 작업의 분할 상환 성능을 유지하기 위해 해시 테이블은 동적으로 크기가 조정되며, 테이블의 항목은 새 해시 테이블의 버킷으로 재해싱된다.[13] 이는 다양한 테이블 크기가 모듈로 연산으로 인해 다른 해시 값을 초래하므로 항목을 단순히 복사할 수 없기 때문이다.[42] 일부 요소를 삭제한 후 해시 테이블이 "너무 비어지면" 과도한 메모리 사용을 피하기 위해 크기 조정을 수행할 수 있다.[43]
모든 엔트리를 이동하여 크기 조정
[편집]일반적으로 원래 해시 테이블 크기의 두 배인 새 해시 테이블이 사적으로 할당되고, 원래 해시 테이블의 모든 항목은 항목의 해시 값을 계산한 후 삽입 작업을 통해 새로 할당된 테이블로 이동된다. 재해싱은 간단하지만 계산 비용이 많이 든다.[44]: 478–479
일괄 재해싱의 대안
[편집]일부 해시 테이블 구현, 특히 실시간 시스템에서는 해시 테이블을 한 번에 모두 확장하는 비용을 지불할 수 없는데, 이는 시간 결정적인 작업을 방해할 수 있기 때문이다. 동적 크기 조정을 피할 수 없다면, 재해싱 중에 (일반적으로 새 테이블 크기의 50%에서) 저장 공간의 순간적인 증가를 피하고, 이전 해시 테이블의 대규모 메모리 블록 해제로 인한 메모리 단편화를 방지하여 힙 압축을 유발하는 솔루션은 점진적으로 크기 조정을 수행하는 것이다.[45]: 2–3 이런 경우 재해싱 작업은 이전 해시 테이블에 할당된 메모리 블록을 확장하여 해시 테이블의 버킷이 변경되지 않도록 점진적으로 수행된다. 분할 상환 재해싱의 일반적인 접근 방식은 두 개의 해시 함수 와 를 유지하는 것이다. 새 해시 함수에 따라 버킷 항목을 재해싱하는 과정은 클리닝이라고 불리며, , 및 와 같은 작업을 커맨드 패턴을 통해 래퍼 로 캡슐화하여 각 버킷의 요소가 재해싱되고 그 절차는 다음과 같이 진행된다.[45]: 3
- 버킷을 청소한다.
- 버킷을 청소한다.
- 명령이 실행된다.
선형 해싱
[편집]선형 해싱은 테이블의 동적 증가 또는 감소를 한 번에 하나의 버킷씩 가능하게 하는 해시 테이블의 구현이다.[46]
성능
[편집]해시 테이블의 성능은 해시 테이블의 엔트리에 대해 준무작위 숫자()를 생성하는 해시 함수의 능력에 달려 있으며, 여기서 , 및 는 키, 버킷의 수 및 해시 함수를 나타내어 이다. 만약 해시 함수가 다른 키()에 대해 동일한 를 생성하면 충돌이 발생하며, 이는 다양한 방식으로 처리된다. 해시 테이블에서 연산의 상수 시간 복잡도()는 해시 함수가 충돌하는 인덱스를 생성하지 않는다는 조건에 따라 가정된다. 따라서 해시 테이블의 성능은 선택된 해시 함수가 인덱스를 분산시키는 능력에 정비례한다.[47]: 1 그러나 이러한 해시 함수를 구성하는 것은 실질적으로 불가능하며, 따라서 구현은 더 높은 성능을 달성하기 위해 사례별 충돌 해결 기술에 의존한다.[47]: 2
해시 함수가 유니버스 요소를 균일하게 분포시키고, 테이블에 저장된 요소가 유니버스에서 무작위로 추출될 때 최상의 성능을 얻을 수 있다. 이 경우 체이닝을 사용한 해싱에서 성공적인 검색의 예상 시간은 이고, 실패한 검색의 예상 시간은 이다.[48]
응용 분야
[편집]연관 배열
[편집]해시 테이블은 많은 유형의 인메모리 테이블을 구현하는 데 일반적으로 사용된다. 이들은 연관 배열을 구현하는 데 사용된다.[33]
데이터베이스 인덱싱
[편집]해시 테이블은 디스크 기반 자료 구조 및 데이터베이스 인덱스(예: dbm 등)로도 사용될 수 있지만, 이러한 응용 분야에서는 B 트리가 더 널리 사용된다.[49]
캐시
[편집]해시 테이블은 캐시를 구현하는 데 사용될 수 있다. 캐시는 주로 느린 미디어에 저장된 데이터에 대한 접근 속도를 높이는 데 사용되는 보조 데이터 테이블이다. 이 응용 프로그램에서 해시 충돌은 충돌하는 두 엔트리 중 하나를 폐기함으로써 처리될 수 있다—일반적으로 테이블에 현재 저장된 오래된 항목을 지우고 새 항목으로 덮어쓰므로, 테이블의 모든 항목은 고유한 해시 값을 가진다.[50][51]
집합
[편집]해시 테이블은 집합 자료 구조의 구현에 사용될 수 있으며, 이는 특정 순서 없이 고유한 값을 저장할 수 있다. 집합은 일반적으로 요소 검색보다는 컬렉션에 값의 멤버십을 테스트하는 데 사용된다.[52]
전치 테이블
[편집]구현
[편집]많은 프로그래밍 언어는 내장 연관 배열 또는 표준 라이브러리 모듈 형태로 해시 테이블 기능을 제공한다.
- 자바스크립트에서 "객체"는 키-값 쌍(속성이라고 함)의 변경 가능한 컬렉션으로, 각 키는 문자열이거나 보장된 고유 "심볼"이다. 다른 값은 키로 사용될 때 먼저 문자열로 강제 변환된다. 일곱 가지 "원시" 데이터 유형 외에, 자바스크립트의 모든 값은 객체이다.[54] ECMAScript 2015는 또한 임의의 값을 키로 허용하는
Map자료 구조를 추가했다.[55] - C++11은 임의의 유형의 키와 값을 저장하기 위한
unordered_map을 표준 라이브러리에 포함한다.[56] - Go의 내장
map은 타입 형태의 맵 타입을 구현하며, 이는 종종 (항상 보장되는 것은 아니지만) 해시 테이블이다.[57] - 자바 프로그래밍 언어에는
HashSet,HashMap,LinkedHashSet및LinkedHashMap제네릭 컬렉션이 포함된다.[58] - 파이썬의 내장
dict는 타입 형태의 해시 테이블을 구현한다.[59] - 루비의 내장
Hash는 루비 2.4부터 개방 주소 지정 모델을 사용한다.[60] - 러스트 프로그래밍 언어는
HashMap,HashSet을 러스트 표준 라이브러리의 일부로 포함한다.[61] - 닷넷.NET 표준 라이브러리에는
HashSet및Dictionary가 포함되어,[62][63] C# 및 VB.NET과 같은 언어에서 사용할 수 있다.[64]
참조
[편집]- ↑ Martin Farach-Colton; Andrew Krapivin; William Kuszmaul. 《Optimal Bounds for Open Addressing Without Reordering》. 2024 IEEE 65th Annual Symposium on Foundations of Computer Science (FOCS). arXiv:2501.02305. doi:10.1109/FOCS61266.2024.00045.
- 1 2 Cormen, Thomas H.; Leiserson, Charles E.; Rivest, Ronald L.; Stein, Clifford (2009). 《Introduction to Algorithms》 3판. Massachusetts Institute of Technology. 253–280쪽. ISBN 978-0-262-03384-8.
- ↑ Mehlhorn, Kurt; Sanders, Peter (2008). 〈Hash Tables and Associative Arrays〉 (PDF). 《Algorithms and Data Structures》. Springer. 81–98쪽. doi:10.1007/978-3-540-77978-0_4. ISBN 978-3-540-77977-3.
- 1 2 3 4 5 6 7 Knuth, Donald E. (1998년 4월 24일). 《The Art of Computer Programming: Volume 3: Sorting and Searching》 2판. Addison-Wesley Professional. ISBN 978-0-201-89685-5.
- ↑ Leiserson, Charles E. (Fall 2005). “Lecture 13: Amortized Algorithms, Table Doubling, Potential Method”. 《course MIT 6.046J/18.410J Introduction to Algorithms》. 2009년 8월 7일에 원본 문서에서 보존된 문서.
- ↑ Cormen, Thomas H.; Leiserson, Charles E.; Rivest, Ronald L.; Stein, Clifford (2001). 〈Chapter 11: Hash Tables〉 2판. 《Introduction to Algorithms》. MIT Press and McGraw-Hill. 221–252쪽. ISBN 978-0-262-53196-2.
- 1 2 3 4 5 Sedgewick, Robert; Wayne, Kevin (2011). 《Algorithms》 4판 1. Addison-Wesley Professional – 프린스턴 대학교, Department of Computer Science 경유.
- ↑ Silberschatz, A.; Korth, H. F.; Sudarshan, S. (2020). 《Database System Concepts》 7판. McGraw-Hill.
- ↑ Goodrich, M. T.; Tamassia, R.; Goldwasser, M. H. (2014). 《Data Structures and Algorithms in Java》 6판. Wiley.
- 1 2 3 Konheim, Alan G. (2010). 《Hashing in Computer Science》. doi:10.1002/9780470630617. ISBN 978-0-470-34473-6.
- 1 2 3 4 5 6 7 8 9 10 11 12 Mehta, Dinesh P.; Mehta, Dinesh P.; Sahni, Sartaj 편집 (2004). 《Handbook of Data Structures and Applications》. doi:10.1201/9781420035179. ISBN 978-0-429-14701-2.
- ↑ Cormen, T. H.; Leiserson, C. E.; Rivest, R. L.; Stein, C. (2009). 《Introduction to Algorithms》 3판. MIT 프레스.
- 1 2 3 4 5 6 7 Mayers, Andrew (2008). “CS 312: Hash tables and amortized analysis”. 코넬 대학교, Department of Computer Science. 2021년 4월 26일에 원본 문서에서 보존된 문서. 2021년 10월 26일에 확인함 – cs.cornell.edu 경유.
- 1 2 James S. Plank and Brad Vander Zanden. "CS140 Lecture notes -- Hashing".
- ↑ Maurer, W. D.; Lewis, T. G. (March 1975). 《Hash Table Methods》. 《ACM Computing Surveys》 7. 5–19쪽. doi:10.1145/356643.356645. S2CID 17874775.
- 1 2 Owolabi, Olumide (February 2003). 《Empirical studies of some hashing functions》. 《Information and Software Technology》 45. 109–112쪽. doi:10.1016/S0950-5849(02)00174-X.
- 1 2 Lu, Yi; Prabhakar, Balaji; Bonomi, Flavio (2006). 《Perfect Hashing for Network Applications》. 2006 IEEE International Symposium on Information Theory. 2774–2778쪽. doi:10.1109/ISIT.2006.261567. ISBN 1-4244-0505-X. S2CID 1494710.
- ↑ Belazzougui, Djamal; Botelho, Fabiano C.; Dietzfelbinger, Martin (2009). 〈Hash, displace, and compress〉 (PDF). 《Algorithms—ESA 2009: 17th Annual European Symposium, Copenhagen, Denmark, September 7–9, 2009, Proceedings》. Lecture Notes in Computer Science. Berlin: Springer. 682–693쪽. CiteSeerX 10.1.1.568.130. doi:10.1007/978-3-642-04128-0_61. MR 2557794.
- 1 2 Cormen, Thomas H.; Leiserson, Charles E.; Rivest, Ronald L.; Stein, Clifford (2001). 〈Chapter 11: Hash Tables〉 2판. 《Introduction to Algorithms》. 매사추세츠 공과대학교. ISBN 978-0-262-53196-2.
- ↑ Stroustrup, Bjarne (1997). 《The C++ Programming Language Third Edition》. Reading Massachusetts: Addison-Wesley. 503쪽. ISBN 0-201-88954-4.
- ↑ Pearson, Karl (1900). 《On the criterion that a given system of deviations from the probable in the case of a correlated system of variables is such that it can be reasonably supposed to have arisen from random sampling》. 《Philosophical Magazine》. Series 5 50. 157–175쪽. doi:10.1080/14786440009463897.
- ↑ Plackett, Robin (1983). 《Karl Pearson and the Chi-Squared Test》. 《International Statistical Review》 51. 59–72쪽. doi:10.2307/1402731. JSTOR 1402731.
- 1 2 Wang, Thomas (March 1997). “Prime Double Hash Table”. 1999년 9월 3일에 원본 문서에서 보존된 문서. 2015년 5월 10일에 확인함.
- ↑ Wegman, Mark N.; Carter, J.Lawrence (June 1981). 《New hash functions and their use in authentication and set equality》. 《Journal of Computer and System Sciences》 22. 265–279쪽. doi:10.1016/0022-0000(81)90033-7.
- ↑ Demaine, Erik; Lind, Jeff (Spring 2003). “Lecture 2” (PDF). 《6.897: Advanced Data Structures. MIT Computer Science and Artificial Intelligence Laboratory》. June 15, 2010에 원본 문서 (PDF)에서 보존된 문서. June 30, 2008에 확인함.
- 1 2 3 Culpepper, J. Shane; Moffat, Alistair (2005). 〈Enhanced Byte Codes with Restricted Prefix Properties〉. 《String Processing and Information Retrieval》. Lecture Notes in Computer Science 3772. 1–12쪽. doi:10.1007/11575832_1. ISBN 978-3-540-29740-6.
- ↑ Willard, Dan E. (2000). 《Examining computational geometry, van Emde Boas trees, and hashing from the perspective of the fusion tree》. 《SIAM Journal on Computing》 29. 1030–1049쪽. doi:10.1137/S0097539797322425. MR 1740562..
- ↑ Askitis, Nikolas; Sinha, Ranjan (October 2010). 《Engineering scalable, cache and space efficient tries for strings》. 《The VLDB Journal》 19. 633–660쪽. doi:10.1007/s00778-010-0183-9.
- ↑ Askitis, Nikolas; Zobel, Justin (October 2005). 〈Cache-conscious Collision Resolution in String Hash Tables〉. 《Proceedings of the 12th International Conference, String Processing and Information Retrieval (SPIRE 2005)》. 91–102쪽. doi:10.1007/11575832_11. ISBN 978-3-540-29740-6.
- ↑ Askitis, Nikolas (2009). 〈Fast and Compact Hash Tables for Integer Keys〉 (PDF). 《Proceedings of the 32nd Australasian Computer Science Conference (ACSC 2009)》. 113–122쪽. ISBN 978-1-920682-72-9. February 16, 2011에 원본 문서 (PDF)에서 보존된 문서. June 13, 2010에 확인함.
- ↑ Tenenbaum, Aaron M.; Langsam, Yedidyah; Augenstein, Moshe J. (1990). 《Data Structures Using C》. Prentice Hall. 456–461, p. 472쪽. ISBN 978-0-13-199746-2.
- 1 2 Pagh, Rasmus; Rodler, Flemming Friche (2001). 〈Cuckoo Hashing〉. 《Algorithms — ESA 2001》. Lecture Notes in Computer Science 2161. 121–133쪽. CiteSeerX 10.1.1.25.4189. doi:10.1007/3-540-44676-1_10. ISBN 978-3-540-42493-2.
- 1 2 3 Cormen, Thomas H.; Leiserson, Charles E.; Rivest, Ronald L.; Stein, Clifford (2001), 〈11 Hash Tables〉 2판, 《Introduction to Algorithms》, MIT 프레스 and McGraw-Hill, 221–252쪽, ISBN 0-262-03293-7.
- 1 2 3 Vitter, Jeffery S.; Chen, Wen-Chin (1987). 《The design and analysis of coalesced hashing》. New York, United States: 옥스퍼드 대학교 출판부. ISBN 978-0-19-504182-8 – Archive.org 경유.
- ↑ Pagh, Rasmus; Rodler, Flemming Friche (2001). 〈Cuckoo Hashing〉. 《Algorithms — ESA 2001》. Lecture Notes in Computer Science 2161. 121–133쪽. CiteSeerX 10.1.1.25.4189. doi:10.1007/3-540-44676-1_10. ISBN 978-3-540-42493-2.
- 1 2 3 4 5 6 Herlihy, Maurice; Shavit, Nir; Tzafrir, Moran (2008). 〈Hopscotch Hashing〉. 《Distributed Computing》. Lecture Notes in Computer Science 5218. 350–364쪽. doi:10.1007/978-3-540-87779-0_24. ISBN 978-3-540-87778-3.
- 1 2 Celis, Pedro (1986). 《Robin Hood Hashing》 (PDF). Ontario, Canada: 워털루 대학교, Dept. of Computer Science. ISBN 978-0-315-29700-5. OCLC 14083698. 2021년 11월 1일에 원본 문서 (PDF)에서 보존된 문서. 2021년 11월 2일에 확인함.
- ↑ Poblete, P. V.; Viola, A. (July 2019). 《Analysis of Robin Hood and Other Hashing Algorithms Under the Random Probing Model, With and Without Deletions》. 《Combinatorics, Probability and Computing》 28. 600–617쪽. doi:10.1017/S0963548318000408. S2CID 125374363.
- ↑ Clarkson, Michael (2014). “Lecture 13: Hash tables”. 코넬 대학교, Department of Computer Science. 2021년 10월 7일에 원본 문서에서 보존된 문서. 2021년 11월 1일에 확인함 – cs.cornell.edu 경유.
- ↑ Gries, David (2017). “JavaHyperText and Data Structure: Robin Hood Hashing” (PDF). 코넬 대학교, Department of Computer Science. 2021년 4월 26일에 원본 문서 (PDF)에서 보존된 문서. 2021년 11월 2일에 확인함 – cs.cornell.edu 경유.
- ↑ Celis, Pedro (1988년 3월 28일). 《External Robin Hood Hashing》 (PDF) (기술 보고서). Bloomington, Indiana: 인디애나 대학교, Department of Computer Science. 246. 2021년 11월 3일에 원본 문서 (PDF)에서 보존된 문서. 2021년 11월 2일에 확인함.
- ↑ Goddard, Wayne (2021). “Chapter C5: Hash Tables” (PDF). 클렘슨 대학교. 15–16쪽. 2023년 12월 4일에 확인함.
- ↑ Devadas, Srini; Demaine, Erik (2011년 2월 25일). “Intro to Algorithms: Resizing Hash Tables” (PDF). 매사추세츠 공과대학교, Department of Computer Science. 2021년 5월 7일에 원본 문서 (PDF)에서 보존된 문서. 2021년 11월 9일에 확인함 – MIT OpenCourseWare 경유.
- ↑ Thareja, Reema (2014). 〈Hashing and Collision〉. 《Data Structures Using C》. Oxford University Press. 464–488쪽. ISBN 978-0-19-809930-7.
- 1 2 Friedman, Scott; Krishnan, Anand; Leidefrost, Nicholas (2003년 3월 18일). 《Hash Tables for Embedded and Real-time systems》 (PDF). 《All Computer Science and Engineering Research》 (워싱턴 대학교 세인트루이스). doi:10.7936/K7WD3XXV. 2021년 6월 9일에 원본 문서 (PDF)에서 보존된 문서. 2021년 11월 9일에 확인함 – 노스웨스턴 대학교, Department of Computer Science 경유.
- ↑ Litwin, Witold (1980). 〈Linear hashing: A new tool for file and table addressing〉 (PDF). 《Proc. 6th Conference on Very Large Databases》. 카네기 멜런 대학교. 212–223쪽. 2021년 5월 6일에 원본 문서 (PDF)에서 보존된 문서. 2021년 11월 10일에 확인함 – cs.cmu.edu 경유.
- 1 2 Dijk, Tom Van (2010). “Analysing and Improving Hash Table Performance” (PDF). 네덜란드: 트벤테 대학교. 2021년 11월 6일에 원본 문서 (PDF)에서 보존된 문서. 2021년 12월 31일에 확인함.
- ↑ Baeza-Yates, Ricardo; Poblete, Patricio V. (1999). 〈Chapter 2: Searching〉. Atallah (편집). 《Algorithms and Theory of Computation Handbook》. CRC Press. 2–6쪽. ISBN 0849326494.
- ↑ Lech Banachowski. “Indexes and external sorting”. pl:Polsko-Japońska Akademia Technik Komputerowych. 2022년 3월 26일에 원본 문서에서 보존된 문서. 2022년 3월 26일에 확인함.
- ↑ Zhong, Liang; Zheng, Xueqian; Liu, Yong; Wang, Mengting; Cao, Yang (February 2020). 《Cache hit ratio maximization in device-to-device communications overlaying cellular networks》. 《China Communications》 17. 232–238쪽. Bibcode:2020CComm..17b.232Z. doi:10.23919/jcc.2020.02.018. S2CID 212649328.
- ↑ Bottommley, James (2004년 1월 1일). “Understanding Caching”. 리눅스 저널. 2020년 12월 4일에 원본 문서에서 보존된 문서. 2022년 4월 16일에 확인함.
- ↑ Jill Seaman (2014). “Set & Hash Tables” (PDF). 텍사스 주립 대학교. 2022년 4월 1일에 원본 문서 (PDF)에서 보존된 문서. 2022년 3월 26일에 확인함.
- ↑ “Transposition Table - Chessprogramming wiki”. 《chessprogramming.org》. 2021년 2월 14일에 원본 문서에서 보존된 문서. 2020년 5월 1일에 확인함.
- ↑ “JavaScript data types and data structures - JavaScript | MDN”. 《developer.mozilla.org》. 2022년 7월 24일에 확인함.
- ↑ “Map - JavaScript | MDN” (미국 영어). 《developer.mozilla.org》. 2023년 6월 20일. 2023년 7월 15일에 확인함.
- ↑ “Programming language C++ - Technical Specification” (PDF). 국제 표준화 기구. 812–813쪽. 2022년 1월 21일에 원본 문서 (PDF)에서 보존된 문서. 2022년 2월 8일에 확인함.
- ↑ “The Go Programming Language Specification”. 《go.dev》. 2023년 1월 1일에 확인함.
- ↑ “Lesson: Implementations (The Java™ Tutorials > Collections)”. 《docs.oracle.com》. January 18, 2017에 원본 문서에서 보존된 문서. April 27, 2018에 확인함.
- ↑ Zhang, Juan; Jia, Yunwei (2020). 《Redis rehash optimization based on machine learning》. 《Journal of Physics: Conference Series》 1453. 3쪽. Bibcode:2020JPhCS1453a2048Z. doi:10.1088/1742-6596/1453/1/012048. S2CID 215943738.
- ↑ Jonan Scheffler (December 25, 2016). “Ruby 2.4 Released: Faster Hashes, Unified Integers and Better Rounding”. 《heroku.com》. July 3, 2019에 원본 문서에서 보존된 문서. July 3, 2019에 확인함.
- ↑ “doc.rust-lang.org”. December 8, 2022에 원본 문서에서 보존된 문서. December 14, 2022에 확인함.
- ↑ “HashSet Class (System.Collections.Generic)” (미국 영어). 《learn.microsoft.com》. 2023년 7월 1일에 확인함.
- ↑ dotnet-bot. “Dictionary Class (System.Collections.Generic)” (미국 영어). 《learn.microsoft.com》. 2024년 1월 16일에 확인함.
- ↑ “VB.NET HashSet Example”. 《Dot Net Perls》.
- 내용주
같이 보기
[편집]외부 링크
[편집]- (영어) A Hash Function for Hash Table Lookup by Bob Jenkins.
- (영어) Hash Tables by SparkNotes—explanation using C
- (영어) Hashmap explanation using Java
- (영어) Hash functions by Paul Hsieh