자료구조 11. 해싱
코드
- 모든 코드는 깃허브에서 확인하실 수 있습니다.
해싱
- 키(key) 값을 이용해 항목을 저장하고 접근하는 자료구조
- 해시 함수: 키 값을 해시 주소로 변경하는 함수
- 해시 테이블(hash table): 해시 함수의 결과에 의해 접근이 가능한 구조
- 딕셔너리(dictionary) 또는 맵(map)으로 불리기도 함
- 슬롯(slot): 값을 저장할 수 있는 공간
- 버켓(bucket): 각각의 해시 주소에 해당하는 값을 저장할 공간
- 슬롯의 집합
해싱의 문제점
- 충돌(collision): 서로 다른 키에 대해 같은 해시 주소가 나오는 문제
- 오버플로우(overflow): 충돌이 버켓에 할당된 슬롯의 수보다 많이 발생하는 것
- 반드시 오버플로우를 해결할 방법이 필요
- 좋은 해시 함수라면 충돌이 적고 해시 주소가 고르게 분포되어야 하며 계산이 빨라야 함
해시 함수
- division method
- key를 테이블의 크기로 나눈 나머지를 주소로 사용
- 비트추출 함수
- 키를 이진수로 간주하여 임의의 위이 k개의 비트를 해시 주소로 사용
- 문자열 해시 함수
- 문자열의 문자를 다 더한 후, 테이블의 크기로 나눈 나머지를 주소로 사용
충돌 해결
- 선형 조사법
- 해시 함수를 통해 생성된 주소에 이미 값이 있을 경우 다음 주소에 값을 저장하는 방법
- 체이닝
- 각 버켓에 연결 리스트를 할당하여 값을 저장하는 방법
문자열 해시 함수 + 체이닝 예시
해시 함수
1 2 3 4 5 6 7 8 9 10 11
unsigned int HashFunction(const char* key) { unsigned long int value = 0; for (int i = 0; i < strlen(key); i++) { value += key[i]; } return value % TABLE_SIZE; }
해시 테이블 구조체
1 2 3 4 5 6 7 8 9 10 11
typedef struct Node { char* key; int value; struct Node* next; } Node; typedef struct { Node** buckets; } HashTable;
Init
1 2 3 4 5 6 7 8 9 10
HashTable* Init() { HashTable* table = (HashTable*)malloc(sizeof(HashTable)); table->buckets = (Node**)malloc(TABLE_SIZE * sizeof(Node*)); for (int i = 0; i < TABLE_SIZE; i++) { table->buckets[i] = NULL; } return table; }
Add
1 2 3 4 5 6 7 8 9
void Add(HashTable* table, const char* key, int value) { unsigned int bucket = HashFunction(key); Node* newNode = (Node*)malloc(sizeof(Node)); newNode->key = _strdup(key); newNode->value = value; newNode->next = table->buckets[bucket]; table->buckets[bucket] = newNode; }
Search
1 2 3 4 5 6 7 8 9 10 11 12 13 14
int Search(HashTable* table, const char* key) { unsigned int bucket = HashFunction(key); Node* node = table->buckets[bucket]; while (node != NULL) { if (strcmp(node->key, key) == 0) { return node->value; } node = node->next; } return -1; }
Delete
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
void Delete(HashTable* table, const char* key) { unsigned int bucket = HashFunction(key); Node* node = table->buckets[bucket]; Node* prev = NULL; while (node != NULL && strcmp(node->key, key) != 0) { prev = node; node = node->next; } if (node == NULL) { return; } if (prev == NULL) { table->buckets[bucket] = node->next; } else { prev->next = node->next; } free(node->key); free(node); }
This post is licensed under CC BY 4.0 by the author.