노트

해시 테이블

Hash Table

CS#algorithm · 연결된 개념 11개

쉽게 말하면

해시 테이블은 이름을 정해진 계산에 넣어 신발장 칸 번호를 얻는 방식이에요. 전체를 뒤지지 않고 그 칸만 열어 보면 되니까, 조회·추가·삭제가 평균적으로 바로 끝나요.

비유가 깨지는 곳 신발장과 달리 서로 다른 키가 같은 칸 번호를 받는 충돌이 생겨요. 충돌이 몰리면 최악 O(n)이 되고, 칸 번호는 순서와 무관해서 정렬된 순서가 필요하면 다른 구조를 써요.

키를 해시 함수(Hash Function)로 배열 인덱스로 바꿔 값을 저장하는 자료구조. 조회·추가·삭제가 평균 O(1)이다. JavaScript의 객체와 Map·Set, 파이썬의 dict·set(파이썬 기본 컬렉션), 자바의 HashMap이 모두 해시 테이블이다.

좋은 해시 함수

  • 빠르다(가능하면 상수 시간)
  • 키를 인덱스 전체에 고르게 퍼뜨린다
  • 같은 입력에는 항상 같은 출력을 낸다(결정적)

테이블 크기를 소수로 잡으면 충돌이 덜 생기는 경향이 있다.

충돌 다루기

서로 다른 키가 같은 인덱스로 가는 충돌(Collision)은 피할 수 없다.

  • 분리 연결법(Separate Chaining): 각 칸에 리스트를 두고 같은 칸에 온 쌍을 이어 붙인다
  • 선형 탐사(Linear Probing): 칸이 차 있으면 다음 빈칸을 찾아 넣는다. 한 칸에 하나만 둔다
function hash(key: string, size: number) {
  let h = 0
  for (const ch of key) h = (h * 31 + ch.charCodeAt(0)) % size
  return h
}

복잡도의 단서

평균은 O(1)이지만 충돌이 몰리면 최악 O(n)이 된다. 채워진 비율(적재율, Load Factor)이 높아지면 테이블을 키워 다시 배치한다. 해시 테이블 자체는 키의 순서를 보장하지 않는다(JavaScript Map과 파이썬 dict는 삽입 순서를 따로 기억한다). 정렬된 순서가 필요하면 다른 구조를 쓴다.

빈도 세기 같은 풀이 패턴과 "배열 find 대신 Map 조회"라는 실무 최적화의 바탕이다(빅오 표기법). 해시는 캐시(LRU 캐시와 캐시 계층 비교)와 샤딩(샤딩)의 데이터 분배에도 쓰인다. 비밀번호 해싱은 이름만 같고 목적이 다른 이야기다(비밀번호 저장: 인코딩·암호화·해싱).

연결된 개념

이 노트를 가리키는 문서

뜻이 가까운 노트

  • 우선순위 큐

    원소마다 우선순위가 있고, 들어온 순서와 상관없이 우선순위가 가장 높은 것부터 꺼내는 추상 자료형(Abstract Data Type, ADT). 같은 우선순위끼리의 순서는 보장하지 않는다. 응급실 대기 순서가 좋은 비유다.

  • 재귀

    함수가 자기 자신을 다시 호출해 문제를 푸는 방식. 같은 함수를 점점 작은 입력으로 부르다가 더 나눌 필요가 없는 지점(기저 조건, Base Case)에서 멈춘다.

  • 정렬 알고리즘

    컬렉션의 원소를 어떤 순서(크기, 사전순, 날짜…)로 다시 배치하는 알고리즘. 같은 일을 하는 방법이 여럿이고 각자 강점이 달라, 트레이드오프를 익히기 좋은 주제다.

  • 이진 탐색

    정렬된 배열에서 가운데 값과 찾는 값을 비교해 매번 절반을 버리며 찾는 방법. 원소가 100만 개여도 20번 남짓이면 끝난다(O(log n)). 처음부터 하나씩 확인하는 선형 탐색(Linear Search)은 O(n)이다.

  • 동적 프로그래밍

    복잡한 문제를 더 작은 부분 문제로 나눠 풀되, 한 번 푼 부분 문제의 답을 저장해 다시 계산하지 않는 방법. 두 조건이 맞을 때 쓴다.

보기 옵션