Data Structure & Algorithm/알고리즘(Algorithm)

07. 해싱

jihyeon99 2024. 7. 5. 10:01

1. 해싱

해싱의 정의
  • 해시함수는 임의의 데이터를 입력받아, 해당 데이터를 고정된 길이의 특정 값으로 반환하는 함수입니다. 즉, 어떤 값을 넣더라도 특정 범위에 해당하는 값을 반환합니다.
  • 만약, 해시 함수의 반환값을 0부터 시작하는 양의 정수가 되도록 조절한다면, 특정 값을 배열(해시 테이블)에 넣기 위해 해시 함수에 그 값을 넣고, 값에 해당하는 인덱스에 그 값을 넣어주는 방법을 사용할 수 있습니다.

function append(key, value)
  set index = hash_function(key)
  hash[index] = value
  
function find(key)
  set index = hash_function(key)
  if hash[index] != null
    return hash[index]
    
function remove(key, value)
  set index = hash_function(key)
  if hash[index] == null
    return 
  hash[index] = null

 

해싱의 장점
  • 해싱은 특정 데이터가 들어온 순서에 상관 없이 삽입, 삭제, 검색이 자주 발생하는 경우에 유용합니다.
  • 해싱을 활용하면 값을 빠르게 삽입하고, 삭제하고, 검색할 수 있습니다. 삽입과 삭제, 검색 모두 해시 함수를 한 번 통과하여 나온 인덱스만 관리하기 때문에, 모두 시간복잡도가 O(1)이 됩니다.

 

해싱의 단점
  • 해시 함수를 사용할 때는 각 타입(문자열, 숫자 등)에 맞는 해시 함수를 사용하여 해시 값으로 바꾸게 되는데, 대응할 수 없는 타입도 존재합니다.
    • ex. 배열 - 배열 내 값의 갯수가 불분명하므로, 일반적으로 해시 함수에선 배열 같은 타입은 다루지 않습니다.
  • 해시 충돌이 발생할 수 있습니다.

 

해시 충돌
  • 해시 충돌은 두 개 이상의 서로 다른 입력 데이터가 동일한 해시 값을 가지는 것을 말합니다. 해시 값의 길이가 제한되어 있기 때문에 무한한 입력 데이터에 대해 고유한 해시 값을 생성하는것은 불가능합니다.
  • 해시 충돌이 일어나는 경우 일반 배열(해시 테이블)로는 해결할 수 없습니다. 이를 해결하기 위해 연결리스트를 사용하는 등 여러 방법이 있습니다.

  • 위에서 만약 해시 함수가 f(x) = x %10이고, 주어진 데이터가 전부 숫자 9로 끝난다면, 삽입, 삭제, 탐색의 경우에 연결리스트를 순회해야하므로 O(N)의 시간복잡도를 갖게 됩니다.

따라서, 해시 함수를 적절하게 설정하여 충돌이 최대한 덜 일어나게 하는 것이 중요합니다. 충돌이 거의 일어나지 않는다면, 해시 함수를 통해 나온 값을 이용하여, 원하는 값을 배열로부터 O(1)의 시간에 바로 조회, 삽입, 삭제할 수 있기 때문입니다. 보통 충돌 자체를 줄이기 위해, 실제로 들어갈 데이터보다 몇 배(3~4배) 정도 더 크게 배열(해시 테이블)을 정의합니다. 하지만, 해시 테이블의 크기를 키우면 충돌은 상대적으로 줄어드나, 메모리를 그만큼 많이 차지하게 됩니다.

 

배열 vs 해싱
  배열 해싱
순서 index기반으로, 담고 있는 데이터간의 순서가 확실하게 매겨져 있으므로, 빠른 인덱스 접근에 유리합니다. 순서 상관 없이, 각각의 데이터가 자주 들어오고 나가는 경우에 유리합니다.
삽입 최악 O(N) 평균 O(1), 최악 O(N)
삭제 최악 O(N) 평균 O(1), 최악 O(N)
검색 어떤 원소를 찾는 경우 : O(N) - 정렬 x
K번째 원소를 찾는 경우 : O(1)
평균 O(1), 최악 O(N)
충돌 문제 없음 있음

 

'Data Structure & Algorithm > 알고리즘(Algorithm)' 카테고리의 다른 글

08. DP  (0) 2024.07.05
06. 트리  (0) 2024.06.30
05. 스택, 큐, 덱  (0) 2024.06.20