본문 바로가기

카테고리 없음

코딩 테스트 합격자 되기 스터디 3주차 - 해시

https://www.inflearn.com/course/cpp-%EC%BD%94%EB%94%A9%ED%85%8C%EC%8A%A4%ED%8A%B8-%ED%95%A9%EA%B2%A9

 

[지금 무료] 코딩 테스트 합격자 되기 - C++ 강의 | dremdeveloper - 인프런

dremdeveloper | 코딩 테스트 합격을 위한 C++ 강의, 책 없이도 가능! 저자와 직접 소통 가능한 커뮤니티 제공!, [사진]여기에 문의 하세요https://open.kakao.com/o/gX0WnTCf📘 코딩 테스트 합격자 되기 - C++편

www.inflearn.com

코딩테스트 합격자 되기 스터디 3주차

해시

  • 해시의 개념
  • 해시 함수
  • 충돌 처리

해시

해시 함수를 사용해서 변환한 값을 인덱스 삼아 키-값을 저장해서 빠른 데이터 탐색을 제공하는 자료구조

(키를 해시함수에 넣으면 인덱스가 나오도록)

키만으로 값의 인덱스를 구할 수 있으므로 빠른 탐색 가능.

배열로 탐색 시 O(N)이지만 해시 함수와 함께라면 O(1)이 된다!

해시함수의 개념

임의의 키를 해시테이블의 인덱스로 변경해주는 함수

→ 해시 테이블의 크기가 N이라면 해시함수는 0~(N-1)사이 값을 내야 함

→ 충돌을 최소화할수록 좋은 해시함수.

  • 서로 다른 키에 대해 해시 함수가 동일 인덱스 반환할 경우 충돌 발생.

해시함수

나눗셈 법

h(x) = x mod k (x는 키, k는 소수)

  • k로 나눈 나머지는 0~(k-1)이므로 해시 테이블의 크기는 k
  • k가 소수인 이유는 충돌을 줄이기 위함(소수가 아니면 k주기로 해시값 반복)

곱셈법

  • 나눗셈법은 k가 소수여야 하므로, 테이블 크기가 커지면 큰 소수가 필요.
  • 곱셈법은 소수 활용하지 않고 황금비를 곱하는 방식
  • h(x) = (((x*A) mod 1))*m x는 키, A는 황금비, m은 최대 버킷 개수

황금비란?
a/b = a/(a+b) = 황금비
대략 1.6180339887…. → 이게 곱셈법의 A

문자열 해싱

  • 문자열의 아스키 코드 값을 활용한 해싱
  • hash(s) = (s[0] + s[1]*p + s[2]*p^2 + … + s[n-1]*p^(n-1)) mod m
  • p는 31(홀수이면서 메르센 소수), m이 테이블 크기
  • 숫자가 금방 커지므로 구현 시 overflow 발생 가능
  • 수정된 공식 사용
  • a = 1, b = 2, c = 3 … z = 26으로 숫자를 매칭하여 사용

(a+b)%c = (a%c + b%c)%c를 활용해서 아래와 같이 구현

  • hash(s) = (s[0] + s[1]*p + s[2]*p^2 + … + s[n-1]*p^(n-1)) mod m

hash(s) = (s[0]%m+s[1]*p%m+s[2]*p^2%m … s[n-1]*p^(n-1)%m)%m

해시 충돌이란?

서로 다른 키에 대해 해시 함수 결과값이 같은 경우 충돌 발생.

  • 체이닝, 개방 주소법이 대표적 해결 방법

체이닝

  • 충돌 발생 시, 해당 버킷에 링크드리스트로 데이터 연결.
  • 특정 버킷에 데이터가 N개인 경우, 원하는 값 찾는 데 O(N)이 걸릴 수 있음.

개방 주소법- 선형탐사

  • 충돌 발생 시, 다른 빈 버킷을 찾아 충돌값 삽입.
  • 최대한 기존 테이블 사용하자는 방식. 메모리 아낄 수 있음
  • h(k, i) = (h(k) + i) mod m
  • k는 키, i는 충돌 시 이동할 버킷 수, m은 버킷 사이즈

개방 주소법 - 이중 해싱

  • 용어 그대로 해시 함수 2개 사용(경우에 따라 N개까지 확장)
  • 기존에 i를 더했던 선형탐사와 다르게 2번째 해시함수에 i를 곱하는 방식도 가능
  • 이 때 클러스터를 줄이기 위해 m을 제곱수나 소수로 함
  • h(k, i) = h1(k) + i*h2(k)) mod m
  • k는 키, i는 임의의 수, h1은 첫번째 해시함수, h2는 두 번째 해시함수, m은 테이블 크기

언제 해시를 활용해서 문제를 풀어야 하나?

  • 키-값 상으로 연관된 데이터가 존재하며, 해당 값에 대한 접근이 빈번한 경우
  • 예를 들어 사전(단어 검색해서 뜻 찾음)이나, 연락처(이름 검색으로 번호 찾음)
  • 중복되지 않는 키를 사용하는 경우
  • 예를 들어 학번이나 집주소

어떤 걸 통해 데이터에 접근할지 고민해봐야함(번호로 이름을 찾으면 의미가 없듯..)