본문 바로가기

개발/C++

C++ HashMap 구현해보기 (unorder_map)

key - > hashfunc -> hash value


hash value 같을때 충돌 회피법


개방주소법 : 다른 주소로 보냄


선형 탐색(Linear Probing) : 해시충돌 시 다음 버켓, 혹은 몇 개를 건너뛰어 데이터를 삽입한다.


제곱 탐색(Quadratic Probing) : 해시충돌 시 제곱만큼 건너뛴 버켓에 데이터를 삽입(1,4,9,16..)


이중 해시(Double Hashing) : 해시충돌 시 다른 해시함수를 한 번 더 적용한 결과를 이용함.


체이닝 : 배열 안에 리스트 std::list[]


최선 : O(1)


최악 : O(n)


, 내부 단편화 가능성 모두 존재


◎ 체이닝(Chaining)의 장점  

 → 연결 리스트만 사용하면 된다. 즉, 복잡한 계산식을 사용할 필요가 개방주소법에 비해 적다.

 → 해시테이블이 채워질수록, Lookup 성능저하가 Linear하게 발생한다. 

◎ 개방주소법(Open Addressing)의 장점 

 → 체이닝처럼 포인터가 필요없고, 지정한 메모리 외 추가적인 저장공간도 필요없다. 

 → 삽입,삭제시 오버헤드가 적다.

 → 저장할 데이터가 적을 때 더 유리하다.



소스 코드 (체이닝)


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
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
#pragma once
#include <iostream>
#include <list>
 
template<typename TKey, typename TValue>
class MyHashMap {
private:
    template<typename TKey, typename TValue>
    struct Data
    {
        TKey key;
        TValue value;
    };
    static int const MAX_COUNT = 5;
    std::list<Data<TKey, TValue>*> bucket[MAX_COUNT];
    int CalcHashFunc(TKey key);
public:
    MyHashMap();
    void Insert(TKey key, TValue value);
    void Delete(TKey key);
    void Print();
};
 
template<typename TKey, typename TValue>
MyHashMap<TKey, TValue>::MyHashMap() {
}
template<typename TKey, typename TValue>
int MyHashMap<TKey, TValue>::CalcHashFunc(TKey key) {
    return key % MAX_COUNT;
}
template<typename TKey, typename TValue>
void MyHashMap<TKey, TValue>::Insert(TKey key, TValue value) {
    std::list<Data<TKey, TValue>*> &list = bucket[CalcHashFunc(key)];
    if (list.size() > 0) {
        for (Data<TKey, TValue> *it : list) {
            if (it->key == key) {
                it->value = value;
                return;
            }
        }
    }
    Data<TKey, TValue>* data = new Data<TKey, TValue>();
    data->key = key;
    data->value = value;
    list.push_back(data);
}
template<typename TKey, typename TValue>
void MyHashMap<TKey, TValue>::Print() {
    for (int i = 0; i < MAX_COUNT; i++) {
        std::list<Data<TKey, TValue>*> list = bucket[i];
        if (list.size() > 0) {
            for (Data<TKey, TValue> *it : list) {
                std::cout << "key : " << it->key << " value : " << it->value << "\t";
            }
        }
        std::cout << std::endl;
    }
}
template<typename TKey, typename TValue>
void MyHashMap<TKey, TValue>::Delete(TKey key) {
    std::list<Data<TKey, TValue>*> &list = bucket[CalcHashFunc(key)];
    if (list.size() > 0) {
        for (Data<TKey, TValue> *it : list) {
            if (it->key == key) {
                list.remove(it);
                return;
            }
        }
    }
}
 
cs





'개발 > C++' 카테고리의 다른 글

C++ 가상 소멸자 (feat. 상속 생성자 소멸자 호출순서)  (0) 2019.04.22
C++ 소켓 에코 채팅 구현하기  (0) 2019.04.15
C++ 맵 구현해보기  (0) 2019.02.23
C++ 리스트 구현해보기  (0) 2019.01.26
C++ 벡터 구현해보기  (0) 2019.01.13