2008-10-22 2 views
14

해시 테이블 (또는 해시 테이블에 구축 된 다른 데이터 구조)이 채워지는 경우 더 많은 버킷으로 새 테이블을 만들어야합니다. 그리고 지금까지 테이블에있는 항목 중 n 개를 입력하면 새 항목에 사용할 버킷 수를 어떻게 계산합니까?해시 버킷의 수

그래서 나는 100 개의 양동이가 있다고 가정 해 보겠습니다. 50 개의 항목이있을 때 재구성해야합니까? 500? 5000? 아니면 내가 가장 가득한 양동이를 찾아야합니까? 그런 다음 내가 그 지점에 도달했을 때 새로운 해시 테이블을 얼마나 크게 만들었습니까?

이와 관련하여, 얼마나 많은 항목이 들어갈 지 미리 아는 경우 양호한 평균 성능을 얻기 위해 버킷 수를 계산할 수있는 방법이 있습니까?

실제 답변은 특정 예에서 속도와 크기가 얼마나 중요한지와 같은 다른 고려 사항에 따라 달라 지지만 일반적인 길드 라인을 찾고 있습니다.

좋은 프로파일 링이 병목 현상이라고 지적하지 않는 한 이런 종류의 것을 최적화해서는 안된다는 것도 알고 있습니다. 나는 많은 해시 테이블을 사용하고 이것을 접근하는 방법을 궁금해하는 프로젝트에 대해서 생각하고있다.

답변

12

해시 테이블이 80 %까지 채워지면 엄지의 좋은 규칙 (항상 이상적이지는 않지만, 엄지 손가락의 규칙)은 다시 해시하는 것입니다. 즉, 100 개의 버켓과 80 개의 아이템이 있다면, 이전에 얼마나 많은 충돌이 있었는지에 관계없이 용량을 늘릴 시간이 있습니다.

얼마나 늘리시겠습니까? 음, 완벽한 가치도 없습니다. 가장 간단한 해결책은 각각의 증가에 따라 용량을 두 배로하는 것입니다. 200, 400, 800 등으로 이동합니다. 이것이 너무 많다고 생각하면 (해시 테이블이 실제로 커지면 16 MB로 8 MB 메모리에서 점프하고 16 MB를 채울 수는 없을 것입니다.) 작은 성장 계수를 선택하십시오. 최소한 1/3은 권장합니다 (100에서 133으로 늘리십시오). 나는 타협으로서 매번 50 % 씩 성장하도록하십시오.

이 모든 것은 충돌이 처리되는 방식에 따라 달라집니다. 그들을 처리하는 간단한 방법 (개인적으로 가장 좋아하는 것)은 충돌이있을 때 연결된 목록에 항목을 저장하는 것입니다. 3 개의 항목이 동일한 키에 배치되면 최대 3 개의 비교 항목 만 찾을 수 있습니다. 연결된 목록은 검색에 매우 효과적이지 않기 때문에 용량을 빠르게 늘릴 수 있습니다. 해시 테이블을 빠르게 유지하기 위해 60 %의 용량이 사용되는 경우. OTOH, 더 정교한 작업을 수행하고 충돌 횟수에 대한 통계를 유지할 수 있습니다. 충돌이 거의 없으면 (아주 ​​좋은 해시 함수가있는 경우) 용량의 99 %가 사용중인 경우에도 해시를 다시 할 필요가 없습니다. 또한 정교한 방식으로 충돌을 처리하는 경우 (예 :각 노드는 다시 정렬 된 테이블이며이 내에서 이진 검색을 수행 할 수 있습니다.) 테이블이 200 %로로드되면 조회가 여전히 빠르기 때문에 용량의 두 배가됩니다. 이 경우 가장 큰 정렬 테이블이 얼마나 큰지 통계를 유지할 수 있으며, 8 개 항목보다 크면 명령이 너무 느려지고 다시 해시되는 것으로 생각할 수 있습니다.

Re-hashing은 매우 느리기 때문에 가능한 한 자주 피해야합니다. 따라서 다시 해시해야하는 경우 용량을 너무 적게 증가시키지 마십시오. 그렇지 않으면 더 많은 항목을 추가 할 때 곧 다시 해시해야합니다. 따라서 다시 해시해야 할 경우 현재 테이블에있는 항목 수보다 용량을 크게 늘리면 나머지는 용량이 너무 적습니다.

8

은 일반적 형식적 정의 부하율 (비공식적 이미했다)에 주목 α   =   N  /  N 총 버킷 사용의 즉 비로. 다른 건 다 정말 실증 시험에 달려있다   <   1.

α 해시 테이블이 제대로 작동하려면 (또는 적어도 수학적 관점에서의 성능 추론하기) 위해서는, 그것은해야한다 : 당신이 볼 경우 해시 테이블이 α  >   0.5에서 양호한 시작을 수행하지 못하면 해당 값을 유지해야합니다. 이 값은 충돌 해결 기술에 따라 다릅니다. 연결을 사용하여 해싱하는 것은 열린 주소 지정으로 해싱하는 것보다 다른로드 요소가 필요할 수 있습니다. 또 다른 요소는 캐시 지역입니다. 테이블이 너무 커지면 주 메모리에 맞지 않습니다. 배열에 대한 액세스가 무작위이므로 캐시에서로드하는 것이 병목 현상이 될 수 있습니다.

1

작성중인 해시 테이블의 유형에 따라 다릅니다. 고정 배열 기반의 해시 테이블 (버킷의 링크 된 목록과 반대)을 사용하는 경우 테이블이 꽉 찼거나 최대 프로브 수를 쳤을 때 배열의 크기를 조정해야합니다 (속도 나 속도가 더 중요한지 여부에 따라 다름) 기억). 연결된 목록을 사용하는 경우 메모리는 별 관심사가 아니므로 빈 공간을 조사 할 필요가 없으므로 크기 조정은 큰 문제가되지 않습니다.

해시 테이블의 키는 버킷의 수가 아니라 해시 알고리즘입니다. 이상적으로는 항상 각 버킷에있는 항목을 하나씩 원하기 때문에 해시 테이블의 항목 수 = 버킷 수일 때 이상적으로 크기를 조정해야합니다. 데이터가 균등하게 분배되지 않으면 더 나은 크기 조정 전략보다 더 나은 해시 알고리즘을 사용하는 것이 좋습니다.

4

일반적으로 두 가지 유형의 해시 테이블이 있습니다 (열림 및 닫힘).

열린 해시 테이블에서 해시를 기반으로 올바른 버킷을 찾은 다음 해당 버킷에서 걸려있는 항목의 목록을 작성합니다.

닫힌 해시 테이블에서 해쉬 값을 사용하여 초기 버킷을 찾고, 점유 된 경우 다음 값을 조사합니다. 단순한 경우에는 다음 무료 버킷을 찾아서이 작업을 수행 할 수 있습니다. 또는 항목에서 두 번째 해시 값을 생성하고 단계별로 작업을 수행 할 수 있습니다 (해시 테이블 크기를 모듈화하여 반드시 확인해야 함). 버킷).

열린 해시 테이블은 일반적으로 크기가 조정되지 않습니다. 초기 크기를 문제에 대해 합리적이라고 느끼는 수준으로 설정합니다. 다른 사람들이 오픈 해시 테이블에서 크기를 조정할 수 있다고 지적했지만이 데이터 구조의 성능에 대한 추론은 이제 매우 어려워졌습니다. 주어진 버킷의 길이가 L 일 때 크기를 조정하면 일 수도 있고은 전체 해시 테이블의 L 항목에서 끝나기 때문에 결국 매우 비효율적입니다.

닫힌 해시 테이블은로드 요소 (해시 테이블의 항목 수/버킷 수)가 미리 정의 된 값에 도달하면 크기가 조정됩니다. 80 %를 사용하는 경향이 있지만 정확한 값은 너무 중요하지는 않습니다.

폐쇄 형 해시 테이블의 이점은 상각 된 항목 삽입 비용이 항상 O (1) (좋은 해시 함수라고 가정)입니다. 특정 항목을 삽입하는 것은 크기 조정 비용으로 인해 O (N) 일 수 있지만 매우 드물게 수행됩니다.

1

선형 해싱을 사용하는 경우 표 자체는 일정한로드 요소를 유지함으로써 자동으로 크기 조정을 처리합니다.

관련 문제