2021. 12. 3. 13:28ㆍDataStructure
개요
대표적인 선형 데이터 구조인 연결리스트(LinkedList)는 삽입과 삭제와 같은 연산에서 낮은 비용으로 수행할 수 있습니다. 그러나 대표적인 단점인 어떤 값을 찾기 위해서는 맨 앞의 노드에서부터 탐색하기 때문에 탐색 속도에서 O(n)의 시간이 소요됩니다. 그렇다고 배열 기반의 리스트를 사용하기에는 삽입과 삭제 연산에서 많은 비용이 발생합니다. 이 문제를 해결하기 위해서 해시를 소개하겠습니다.
- 해시소개
- 해시함수 작성시 고려사항
- 해시충돌이란 무엇인가?
1. 해시 소개
해시는 특정한 키(key)값을 해시 함수(HashFunction)의 수식에 대입시켜 계산 후 나온 결과를 주소로 사용하여 값(Value)에 접근하는 방법입니다.
예를 들어 학생의 아이디(Student ID)와 점수(Grade)가 아래와 같다고 가정합니다.
Student ID | Grade |
CSSC10 | 92 |
CSSC11 | 100 |
... | ... |
CSSC99 | 84 |
만약 연결리스트로 학생들의 ID와 점수를 저장한다면 99번째 학생의 정보를 찾기 위해서는 89번의 탐색(O(n))을 수행해야 할 것입니다. 하지만 Student ID에서 CSSC 부분을 제외한 끝에 숫자 부분을 이용하면 배열에 저장할 수 있을 것 같습니다. 그러나 배열은 0번째부터 시작하기 때문에 0번째부터 시작하기 위해서 -10을 연산하면 0번재부터 저장이 가능할 것입니다. 위와 같은 과정이 해시 함수의 수식의 내용이며 정리하면 아래와 같습니다.
int hashFunction(String id)
{
remove CSSC // StudentID에서 CSSC 문자열 제거
convert to int // 문자열 타입의 숫자를 정수로 변환
int - 10 // 정수에서 -10 수행
return int // -10 수행한 것을 반환 (인덱스 반환)
}
위의 해시 함수를 예제에 적용하면 아래와 같습니다.
StudentID | hashFunction(String id) |
CSSC10 | 0 |
CSSC11 | 1 |
CSSC12 | 2 |
... | ... |
CSSC99 | 89 |
위의 예제에서 StudentID와 Grade를 배열에 저장한다면 아래와 같이 저장될 것입니다.
위와 같이 해시를 사용하면 배열처럼 빠르게 데이터를 탐색할 수 있고 연결리스트처럼 데이터를 빠르게 추가하거나 제거할 수있습니다. 그리고 연결리스트처럼 모든 노드의 데이터를 확인하는 것이 아닌 키(key)가 주어지면 값이 저장된 위치를 바로 접근할 수 있습니다.
2. 해시 함수 작성시 고려사항
- 데이터의 속성 : 예를 들어, CSSC 아이디가 존재한다면 CSSC 부분을 제거해야 함
- 연산이 빨라야 함
- 두 요소가 "같다면" 같은 값을 반환해야 함
- 같은 실행 환경일 경우 같은 객체라면 같은 값이 나와야 함
- 코드를 새로 실행하면 객체가 같더라도 다른 값이 나올 수 있음
- 예를 들어 Object 클래스의 hashcode 메서드는 메모리 위치 기반으로 실행됩니다. 객체의 hashcode 메서드는 함수를 호출하지 않으면 실행할때 마다 객체는 메모리 위에서 다른 위치에 저장되기 때문에 다른 값이 반환됩니다.)
- 코드에서 최대한 충돌(Collision)이 일어나지 않도록 해야함
3. 해시 충돌이란 무엇인가?
해시 충돌이란 서로 다른 값을 가진 키가 일치하는 상황을 의미합니다. 예를 들어 전화번호를 3분할 한 것을 키로 지정했을때 아래와 같은 상황이 발생할 수 있습니다.
위 상황은 핸드폰 번호를 키값으로 하여 해시 함수에 넣어 저장될 인덱스를 계산하는 상황입니다. 해시 함수 수식의 내용은 핸드번 번호를 입력으로 받으면 앞에서부터 3자리씩 분할하여 더하는 수식입니다. 그런데 위의 그림과 같이 010-1234-5678, 010-1204-5681 두 번호는 키값이 다른데도 불구하고 해시 함수의 결과로 같은 값이 나오게 되어 중복되는 상황이 발생하였습니다. 위와 같이 해시 함수의 결과가 같게 나오는 현상을 해시 충돌이라고 부릅니다.
References
[부스트코스] 자바로 구현하고 배우는 자료구조
'DataStructure' 카테고리의 다른 글
비선형 데이터구조, 해시(Hash) #3 해시 크기 최적화 및 양수로 전환 (0) | 2021.12.03 |
---|---|
비선형 데이터구조, 해시(Hash) #2 해시함수에서 문자열 (0) | 2021.12.03 |
비선형 데이터구조, 힙(Heap) #3 Priority Queue in Java (0) | 2021.09.29 |
비선형 데이터구조, 힙(Heap) #1 이진 힙(Binary Heap) (0) | 2021.09.28 |
비선형 데이터구조, 트리(Tree) #9 TreeSet in Java (0) | 2021.09.28 |