Notice
Recent Posts
Recent Comments
Link
«   2024/12   »
1 2 3 4 5 6 7
8 9 10 11 12 13 14
15 16 17 18 19 20 21
22 23 24 25 26 27 28
29 30 31
Tags
more
Archives
Today
Total
관리 메뉴

Finn의 개발블로그

10. hash 본문

자료구조

10. hash

BeginnerFinn 2018. 12. 4. 00:05

해시에 대한 이미지 검색결과


1. Hash 

- hash 는 내부적으로 배열을 사용하여 데이터를 저장하기 때문에 속도가 빠름

- 특정한 값을 Search할때 데이터 고유의 index로 접근 하기에 평균의 시간 복잡도가 Big-O(1)된다

- Collision 때문에 항상 Big-O(1)은 아니다

- 특별한 알고리즘(hash function)을 이용하여 저장할 데이터와 연관된 고유한 숫자를 만들어 데이터의 index에 사용한다 

- 특정 데이터의 인덱스는 고유한 위치라서, 삽입 연산 시 다른 데이터의 사이에 끼어들거나, 삭제 연산 시 다른 데이터로 채울 필요가 없기 때문에 추가적인 비용이 들지 않는 자료구조이다


2. Hash function

- hash function에 의해 반환된 데이터의 고유의 숫자 값을 hashcode

- 어설플 hash function은 동일한 key값에 복수 개의 데이터가 하나의 테이블에 존재할 수 있게 되는데 이것을 Collision 이라고 한다.

- Collision 이란 서로 다른 두개의 키가 같은 인덱스로 hashing(hash 함수를 통해 계산됨을 의미)되면 같은 곳에 저장할 수 없게 되는 것.

- hash function을 무조건 1:1로 만드는 것보다 Collision을 최소하하는 방향으로 설계하고 발생하는 Collision에 대비해 어떻게 대응하는할 것 인가가 중요


3. Resolve Conflict

1. Open Address 방식 (개방주소법)

해시 충돌이 발생하면, 다른 해시 버킷에 해당 자료를 삽입하는 방식

- 버킷이란 데이터를 저장하기 위한 공간

- Collision이 발생하면 데이터 저장할 장소를 찾는다 Worst Case의 경우 비어있는 버킷을 찾지 못하고 탐색을 시작한 위치까지 되돌아 올 수 있다.

- 비어있는 버킷을 찾는 방식에는 세 가지 방식이 있다

1. Linear Probing

- 순차적으로 탐색하며 비어있는 버킷을 찾을 때까지 계속 진행

2. Quadratic probing

- 해쉬 함수를 2차 식으로 만든다

3. Double Hashing probing

- 하나의 해쉬 함수에서 충돌이 발생하면 2차 해쉬 함수를 이용해 새로운 주소를 할당한다. Linear, Quadratic 방식들에 비해 연산량이 많다


2. Separate Chaining 방식 (분리 연결법)

- Open Addressing은 Separate Chaining보다 느리다.

- Open Addressing의 경우 해시 버킷을 채운 밀도가 높아질수록 Worst Case 발생 빈도가 더 높아지기 때문

- Separate Chaining 방식의 경우 해시 충돌이 잘 발생하지 않도록 보조 해시 함수를 통해 조정할 수 있다면 Worst Case에 가까워 지는 빈도를 줄일 수 있다 

- Separate Chaining 방식에느 두 가지 구현 방식이 존재

1. Linked List를 이용하는 방식

- 각각의 버킷들은 연결리스트로 만들어 Collision이 발생하면 해당 bucket의 list에 추가하는 방식

- 연결리스트의 특징을 그대로 이어받아 삭제 또는 삽입이 간단

- 연결리스트의 단점인 작은 데이터들을 저장할 때 연결 리스트 자체의 오버헤드가 부담

- 버킷을 계속해서 사용하는 Open Address 방식에 비해 테이블 확장을 늦출 수 있다


2. Tree를 이용하는 방식

- 연결리스트 대신 트리르 사용하는 방식

- 연결리스트를 사용할 것인가 트리를 사용할 것인가 대한 기준은 하나의 해시 버킷에 할당된 key-value 쌍의 개수이다.

- 이 key-value 쌍의 개수가 6개, 8개를 기준으로 결정한다. (6개 연결리스트, 8개 트리)

- 만약 기준이 6,7 이라면 6 -> 7로 될때 트리로 변경해야하고 다시 삭제한다면 연결리스트로 자료구조를 다시 변경해야 한다.

- 기준이 1이라면 Switching 비용이 너무 많이 필요하게 된다. 그래서 2라는 여유를 남겨두고 기준을 잡아준다.


3. Open Address vs Separate Chaining

- 두 방식 모두 Worst Case 에서 O(M)이다.

- Open Address 방식은 연속된 공간에 데이터를 저장하기 떄문에 Separate Chaining에 비해 캐시 효율이 높다.

Separate Chaining 방식에 비해 Open Address 방식은 버킷을 계속해서 사용하기 때문에 Separate Chaining 방식은 테이블의 확장을 늦출 수 있다.



4. 보조 해시 함수

- 보조 해시 함수의 목적은 key의 해시 값을 변경하여 해시 충돌 가능성을 줄이는 것이다. Separate Chaining 방식을 사용할 때 함계 사용되며 보조 해시 함수로 Worst Case에 가까워지는경우를 줄일 수 있다


5. 해시 버킷 동적 확장(Resize)

- 해시 버킷의 개수가 적다면 메모리 사용을 아낄 수 있지만 해시 충돌로 인해 성능 상 손실 발생한다

- HashMap은 key-value쌍 데이터 개수가 일정 개수 이상이 되면 해시 버킷의 개수를 두 배로 늘린다

- 해시 버킷 크기를 두 배로 확장하는 임계점은 현재 데이터 개수가 해시 버킷의 개수의 75%가 될 때이다

- 0.75라는 숫자는 load factor라고 부른다

'자료구조' 카테고리의 다른 글

11. Graph  (0) 2018.12.09
9. 레드 블랙 트리  (0) 2018.11.25
8. 힙  (0) 2018.11.13
7. 트리  (0) 2018.11.11
6. 큐  (0) 2018.11.07