ํฌ์ŠคํŠธ

CS โ€” hash rehash followup

CS โ€” hash rehash followup

๐Ÿ“• 15-2 โ€” ํ•ด์‹œ ์ž๋ฃŒ๊ตฌ์กฐ์˜ capacityยทload factorยทrehash

15_1_vector_vs_hash_concepts.md ์˜ ํ›„์†ํŽธ. ํ•ด์‹œ ํ…Œ์ด๋ธ”์ด ๋‚ด๋ถ€์ ์œผ๋กœ ์–ด๋–ป๊ฒŒ ํฌ๊ธฐ๋ฅผ ๊ด€๋ฆฌํ•˜๊ณ , ์–ธ์ œ ๋น„์‹ผ rehash๊ฐ€ ์ผ์–ด๋‚˜๋Š”์ง€ ์ •๋ฆฌ.


1. capacity (๋ฒ„ํ‚ท ์ˆ˜) โ€” ํ•ด์‹œ ํ…Œ์ด๋ธ”์˜ ๋‚ด๋ถ€ ๋ฐฐ์—ด ํฌ๊ธฐ

ํ•ด์‹œ ํ…Œ์ด๋ธ”์€ ๋‚ด๋ถ€์— ๋ฒ„ํ‚ท ๋ฐฐ์—ด(bucket array) ์„ ๊ฐ€์ง€๊ณ , ๊ฐ ํ‚ค๋ฅผ hash(key) % bucket_count ๋กœ ๋ฒ„ํ‚ท์— ๋ถ„๋ฐฐํ•ฉ๋‹ˆ๋‹ค.

1
2
3
4
5
6
7
bucket_count = 8 ์ผ ๋•Œ

idx:  0    1    2    3    4    5    6    7
     [ ]  [โ—]  [ ]  [โ—โ†’โ—][ ]  [โ—]  [ ]  [ ]
           โ†‘        โ†‘โ†‘        โ†‘
           key1     key2 key3  key4
                   (์ถฉ๋Œ โ†’ ์ฒด์ธ)
  • size() โ€” ํ˜„์žฌ ์ €์žฅ๋œ ํ‚ค-๊ฐ’ ์Œ ๊ฐœ์ˆ˜
  • bucket_count() โ€” ๋‚ด๋ถ€ ๋ฒ„ํ‚ท ๋ฐฐ์—ด ํฌ๊ธฐ (capacity ์—ญํ• )

vector::capacity()๊ฐ€ โ€œ์žฌํ• ๋‹น ์—†์ด ๋“ค์–ด๊ฐˆ ์ˆ˜ ์žˆ๋Š” ์›์†Œ ์ˆ˜โ€์˜€๋‹ค๋ฉด, ํ•ด์‹œ์˜ bucket_count()๋Š” โ€œrehash ์—†์ด ๋ถ„๋ฐฐํ•  ์ˆ˜ ์žˆ๋Š” ์Šฌ๋กฏ ์ˆ˜โ€ ์ž…๋‹ˆ๋‹ค.


2. load factor โ€” ํ‰๊ท  ์ถฉ๋Œ ์ •๋„์˜ ์ง€ํ‘œ

1
load_factor = size / bucket_count
  • load_factor = 0.5 โ†’ ํ‰๊ท  ๋‘ ๋ฒ„ํ‚ท์— ํ•œ ์›์†Œ (์ถฉ๋Œ ๊ฑฐ์˜ ์—†์Œ)
  • load_factor = 1.0 โ†’ ํ‰๊ท  ํ•œ ๋ฒ„ํ‚ท์— ํ•œ ์›์†Œ
  • load_factor = 2.0 โ†’ ํ‰๊ท  ํ•œ ๋ฒ„ํ‚ท์— ๋‘ ์›์†Œ (์ถฉ๋Œ ๋นˆ๋ฒˆ)

load factor๊ฐ€ ๋†’์„์ˆ˜๋ก ์ถฉ๋Œ์ด ๋Š˜์–ด๋‚˜ ํ•œ ๋ฒ„ํ‚ท์˜ ์ฒด์ธ์ด ๊ธธ์–ด์ง€๊ณ , find/insert๊ฐ€ ํ‰๊ท  O(1)์—์„œ ๋ฉ€์–ด์ง‘๋‹ˆ๋‹ค. ๊ทธ๋ž˜์„œ ํ‘œ์ค€์€ ์ž„๊ณ„๊ฐ’์„ ๋‘๊ณ  ์ž๋™์œผ๋กœ bucket์„ ๋Š˜๋ฆฝ๋‹ˆ๋‹ค.

1
2
3
std::unordered_map<int, int> m;
std::cout << m.max_load_factor();   // 1.0 (C++ ํ‘œ์ค€ ๊ธฐ๋ณธ)
m.max_load_factor(0.5);             // ๋” ๋นก๋นกํ•˜๊ฒŒ (๋ฉ”๋ชจ๋ฆฌ โ†‘, ์ถฉ๋Œ โ†“)

max_load_factor ๋ฅผ ์ž‘๊ฒŒ ์žก์œผ๋ฉด ์ถฉ๋Œ์ด ์ค„์ง€๋งŒ ๋ฉ”๋ชจ๋ฆฌ ์‚ฌ์šฉ๋Ÿ‰ ์ฆ๊ฐ€ (๊ฐ™์€ size์— ๋” ํฐ bucket_count). ํŠธ๋ ˆ์ด๋“œ์˜คํ”„.


3. rehash โ€” ์ž„๊ณ„๊ฐ’ ์ดˆ๊ณผ ์‹œ ์ž๋™ ์žฌํ•ด์‹ฑ

load_factor > max_load_factor ๊ฐ€ ๋˜๋Š” ์ˆœ๊ฐ„ rehash๊ฐ€ ์ž๋™ ํŠธ๋ฆฌ๊ฑฐ๋ฉ๋‹ˆ๋‹ค.

1
2
3
4
5
6
7
8
9
10
[insert ์‹œ์ ]
    โ†“
load_factor ๊ณ„์‚ฐ
    โ†“
> max_load_factor?
    โ”œ NO  โ†’ ๊ทธ๋ƒฅ ์‚ฝ์ž… (ํ‰๊ท  O(1))
    โ”” YES โ†’ rehash ๋ฐœ๋™
              โ”œ bucket_count๋ฅผ ๋ณดํ†ต 2๋ฐฐ๋กœ ์ฆ๊ฐ€
              โ”œ ๋ชจ๋“  ์›์†Œ๋ฅผ ์ƒˆ bucket_count์— ์žฌํ•ด์‹ฑ
              โ”” ๋น„์šฉ: O(N) โ† ํ•œ ๋ฒˆ์— ๋ชจ๋“  ์›์†Œ ์ด๋™

rehash๋Š” ๋‹จ๋ฐœ์ ์œผ๋กœ O(N) ๋น„์šฉ. amortized๋กœ๋Š” ์—ฌ์ „ํžˆ O(1)์ด์ง€๋งŒ ๊ทธ ์ˆœ๊ฐ„ ํ”„๋ ˆ์ž„์ด ํ•œ ๋ฒˆ ๊ธธ์–ด์ง.

1
2
3
// ์ˆ˜๋™ rehash
m.rehash(N);     // bucket_count๋ฅผ N ์ด์ƒ์œผ๋กœ ์„ค์ •
m.reserve(N);    // N๊ฐœ ์›์†Œ ๋“ค์–ด๊ฐ€๋„ rehash ์—†๊ฒŒ โ€” ๊ถŒ์žฅ ํŒจํ„ด

reserve(N)์€ ๋‚ด๋ถ€์ ์œผ๋กœ rehash(ceil(N / max_load_factor)) ํ˜ธ์ถœ. ์‚ฌ์šฉ์ž๊ฐ€ ์ž์ฃผ ์“ฐ๋Š” API.


4. rehash ๋น„์šฉ โ€” ๊ฒŒ์ž„ ๋ฃจํ”„์—์„œ ์œ„ํ—˜

1
2
3
4
5
6
7
// ๊ฒŒ์ž„ ๋ฃจํ”„ (60fps = 16.6ms ํ”„๋ ˆ์ž„ ์˜ˆ์‚ฐ)
std::unordered_map<FName, FEnemyData> Enemies;

void Tick(float Dt) {
    SpawnEnemy(...);   // ๋งค ํ”„๋ ˆ์ž„ enemies ์ถ”๊ฐ€
    // ...
}

์Œ“์ด๋‹ค๊ฐ€ ์–ด๋А ํ”„๋ ˆ์ž„์—์„œ rehash ํŠธ๋ฆฌ๊ฑฐ๋˜๋ฉด ๊ทธ ํ”„๋ ˆ์ž„๋งŒ ๊ฐ‘์ž๊ธฐ 5~10ms ์‚ฌ์šฉ โ†’ ํ”„๋ ˆ์ž„ ๋“œ๋กญ. ๊ฒŒ์ž„ ์ฝ”๋“œ์—์„œ ๊ฐ€์žฅ ํ”ํ•œ hash ํ•จ์ •.

ํ•ด๊ฒฐ โ€” ์‹œ์ž‘ ์‹œ reserve(N):

1
2
3
void BeginPlay() {
    Enemies.reserve(1024);   // ์˜ˆ์ƒ ์ตœ๋Œ€์น˜ ๋ฏธ๋ฆฌ ํ™•๋ณด
}

vector์˜ reserve(N)๊ณผ ๊ฐ™์€ ์ฒ ํ•™ โ€” ๋ฏธ๋ฆฌ ์•Œ๋ฉด ๋ฏธ๋ฆฌ ์žก๊ณ , ๋Ÿฐํƒ€์ž„ ์ค‘ ์žฌํ• ๋‹น/rehash ํšŒํ”ผ.


5. ๋‹ค์ด์–ด๊ทธ๋žจ โ€” ์‚ฝ์ž…๊ณผ rehash

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
์ดˆ๊ธฐ ์ƒํƒœ (bucket_count=4, max_load=1.0):

idx:  0    1    2    3
     [ ]  [ ]  [ ]  [ ]

insert(k1)  size=1, load=0.25  โ†’ ์ •์ƒ ์‚ฝ์ž…
insert(k2)  size=2, load=0.5   โ†’ ์ •์ƒ ์‚ฝ์ž…
insert(k3)  size=3, load=0.75  โ†’ ์ •์ƒ ์‚ฝ์ž…
insert(k4)  size=4, load=1.0   โ†’ ์ •์ƒ ์‚ฝ์ž… (=์ž„๊ณ„๊ฐ’)
insert(k5)  size=5, load=1.25  โ†’ โ˜… ์ž„๊ณ„๊ฐ’ ์ดˆ๊ณผ
                                  โ†“
                          rehash ๋ฐœ๋™
                                  โ†“
                     bucket_count: 4 โ†’ 8 (๋ณดํ†ต 2๋ฐฐ)
                                  โ†“
                     ๋ชจ๋“  ์›์†Œ (k1~k4) ์žฌํ•ด์‹ฑ
                                  โ†“
                     k5 ์ •์ƒ ์‚ฝ์ž…
                                  โ†“
                     ์ด insert๋งŒ O(N) ๋น„์šฉ

์ดํ›„ ์ƒํƒœ (bucket_count=8):

idx:  0    1    2    3    4    5    6    7
     [โ—]  [ ]  [โ—]  [ ]  [โ—]  [โ—]  [ ]  [โ—]
      k1        k2        k3   k4        k5

6. ์–ธ๋ฆฌ์–ผ TMap โ€” ๊ฐ™์€ ์›๋ฆฌ, ๋‹ค๋ฅธ API

์–ธ๋ฆฌ์–ผ์˜ TMap<K, V>๋„ ๋‚ด๋ถ€์ ์œผ๋กœ hash ํ…Œ์ด๋ธ”(sparse array + hash). ํ•ต์‹ฌ API:

1
2
3
4
5
6
7
TMap<int32, FString> Map;

Map.Reserve(1024);    // N๊ฐœ ๋“ค์–ด๊ฐ€๋„ ์žฌํ• ๋‹น ์—†๊ฒŒ
Map.Empty(1024);      // Clear + Reserve(1024)
Map.Compact();        // ๋นˆ ์Šฌ๋กฏ ์ œ๊ฑฐ (sparse ์ •๋ฆฌ)

int32 BucketCount = Map.GetMaxIndex();   // ๋‚ด๋ถ€ ์Šฌ๋กฏ ์ˆ˜

Reserve๋Š” STL๊ณผ ๊ฐ™์€ ์˜๋ฏธ. Empty(N)์€ clearํ•˜๋ฉด์„œ capacity ์œ ์ง€/์กฐ์ •. ๊ฒŒ์ž„ ์‹œ์ž‘์ด๋‚˜ ๋ ˆ๋ฒจ ๋กœ๋“œ ์‹œ ์˜ˆ์ƒ ์ตœ๋Œ€์น˜๋กœ Reserve ํ•ด๋‘๋Š” ๊ฒŒ ํ‘œ์ค€ ํŒจํ„ด.

์–ธ๋ฆฌ์–ผ์˜ TMap์€ STL๊ณผ ๋‹ฌ๋ฆฌ ์‚ฝ์ž… ์ˆœ์„œ๋ฅผ ๋ณด์กดํ•ฉ๋‹ˆ๋‹ค (sparse array ๊ธฐ๋ฐ˜) โ€” ๊ทธ๋ž˜์„œ ์ดํ„ฐ๋ ˆ์ด์…˜ ์ˆœ์„œ๊ฐ€ ๊ฒฐ์ •์ . ๋‹จ, ์‚ญ์ œ ํ›„ ์žฌ์‚ฝ์ž… ์‹œ ์ˆœ์„œ๊ฐ€ ๋‹ฌ๋ผ์งˆ ์ˆ˜ ์žˆ์Œ.


7. ๋ฉด์ ‘ Q&A

Q1. โ€œunordered_map๊ณผ map์˜ ์‹œ๊ฐ„๋ณต์žก๋„ ์ฐจ์ด๋Š”?โ€

std::map์€ ํ•ญ์ƒ O(log N), std::unordered_map์€ ํ‰๊ท  O(1) ์ตœ์•… O(N).

std::map์€ Red-Black Tree(์ž๊ฐ€ ๊ท ํ˜• ์ด์ง„ ๊ฒ€์ƒ‰ ํŠธ๋ฆฌ). ๋ชจ๋“  ์—ฐ์‚ฐ(find/insert/erase)์ด ํŠธ๋ฆฌ ๋†’์ด์— ๋น„๋ก€ํ•œ O(log N)์ด๊ณ , ์ตœ์•…๋„ O(log N)์œผ๋กœ ๋ณด์žฅ. ํ‚ค ์ˆœ์„œ๊ฐ€ ์ •๋ ฌ๋ผ์„œ ์ˆœํšŒ ์‹œ ์˜ค๋ฆ„์ฐจ์ˆœ.

std::unordered_map์€ hash table. ํ‰๊ท ์€ O(1)์ด์ง€๋งŒ load factor๊ฐ€ ๋†’์•„์ง€๊ฑฐ๋‚˜ hash ์ถฉ๋Œ์ด ์‹ฌํ•˜๋ฉด ํ•œ ๋ฒ„ํ‚ท์˜ ์ฒด์ธ์ด ๊ธธ์–ด์ ธ ์ตœ์•… O(N). ๊ทธ๋ฆฌ๊ณ  rehash ์‹œ ๊ทธ ํ•œ ๋ฒˆ์˜ insert๋Š” O(N) ๋น„์šฉ โ€” amortized O(1)์ด์ง€๋งŒ worst-case๋Š” ๋‹ค๋ฆ„.

๊ทธ๋ž˜์„œ ์„ ํƒ ๊ธฐ์ค€:

  • ์ˆœ์„œ๊ฐ€ ์ค‘์š”ํ•˜๊ฑฐ๋‚˜ worst-case ๋ณด์žฅ์ด ํ•„์š” โ†’ std::map (RB-Tree)
  • ํ‰๊ท  ๋น ๋ฅธ lookup์ด ์šฐ์„ ์ด๊ณ  ์ˆœ์„œ ๋ฌด๊ด€ โ†’ std::unordered_map (hash)
  • ๋ฉ”๋ชจ๋ฆฌ๊ฐ€ ๋น ๋“ฏํ•˜๊ฑฐ๋‚˜ capacity ์˜ˆ์ธก ๊ฐ€๋Šฅ โ†’ std::unordered_map + reserve

์‹ค์ œ ๋ฒค์น˜๋งˆํฌ๋กœ๋Š” unordered_map์˜ ํ‰๊ท ์ด ์•ฝ 2~3๋ฐฐ ๋น ๋ฅธ ๊ฒฝ์šฐ๊ฐ€ ๋งŽ์ง€๋งŒ, ์ž‘์€ N(< 30)์—์„œ๋Š” map์ด ๋” ๋น ๋ฅผ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค(cache ์นœํ™”์„ฑ). N์ด ๋งค์šฐ ํฌ๊ณ  lookup์ด hot path๋ฉด unordered_map์ด ์šฐ์„ธ.

Q2. โ€œrehash๊ฐ€ ์ผ์–ด๋‚˜๋Š” ์‹œ์ ๊ณผ ๋น„์šฉ์€?โ€

์‹œ์  โ€” insert ํ›„ load_factor > max_load_factor ๊ฐ€ ๋˜๋Š” ์ˆœ๊ฐ„. C++ ํ‘œ์ค€ ๊ธฐ๋ณธ max_load_factor = 1.0 ์ด๋ฏ€๋กœ, size๊ฐ€ bucket_count๋ฅผ ์ดˆ๊ณผํ•˜๋ ค๋Š” ์ˆœ๊ฐ„ ํŠธ๋ฆฌ๊ฑฐ.

๋น„์šฉ โ€” bucket_count๋ฅผ ๋ณดํ†ต ๋‘ ๋ฐฐ๋กœ ๋Š˜๋ฆฌ๊ณ , ๋ชจ๋“  N๊ฐœ ์›์†Œ๋ฅผ ์ƒˆ bucket_count์— ์žฌํ•ด์‹ฑ. ์‹œ๊ฐ„ ๋ณต์žก๋„ O(N). ๋ฉ”๋ชจ๋ฆฌ๋Š” ์ž ์‹œ ๋‘ ๋ฐฐ ์‚ฌ์šฉ(์ด์ „ ๋ฐฐ์—ด + ์ƒˆ ๋ฐฐ์—ด). ํ•œ ๋ฒˆ์˜ insert๊ฐ€ ๊ทธ ์ˆœ๊ฐ„๋งŒ O(N).

amortized ๋ถ„์„ โ€” N๊ฐœ ์›์†Œ๋ฅผ ์ฒ˜์Œ๋ถ€ํ„ฐ insertํ•˜๋ฉด rehash๊ฐ€ log N๋ฒˆ ์ •๋„ ๋ฐœ์ƒ(bucket์ด 2๋ฐฐ์”ฉ ์ฆ๊ฐ€ํ•˜๋ฏ€๋กœ). ์ด ๋น„์šฉ O(N log N)์ด์ง€๋งŒ N์œผ๋กœ ๋‚˜๋ˆ„๋ฉด amortized O(log N / log N) = O(1). ๊ทธ๋ž˜์„œ ํ‰๊ท ์€ ์—ฌ์ „ํžˆ ๋น ๋ฅด์ง€๋งŒ ๊ฐœ๋ณ„ insert๋Š” ์ตœ์•… O(N).

๊ฒŒ์ž„ ์ฝ”๋“œ์—์„œ ์œ„ํ—˜ โ€” 16.6ms ํ”„๋ ˆ์ž„ ์˜ˆ์‚ฐ ์•ˆ์— ๊ฐ‘์ž๊ธฐ 5~10ms rehash๊ฐ€ ๋ผ๋ฉด ํ”„๋ ˆ์ž„ ๋“œ๋กญ. ๊ทธ๋ž˜์„œ reserve(N)์œผ๋กœ ์˜ˆ์ƒ ์ตœ๋Œ€์น˜ ๋ฏธ๋ฆฌ ํ™•๋ณด๊ฐ€ ํ‘œ์ค€. ์–ธ๋ฆฌ์–ผ TMap๋„ ๊ฐ™์€ ์›๋ฆฌ๋กœ Reserve/Empty(N) ๊ถŒ์žฅ.

ํ•œ ๊ฐ€์ง€ ์ถ”๊ฐ€ โ€” rehash ํ›„ ๋ชจ๋“  ์ดํ„ฐ๋ ˆ์ดํ„ฐยท์ฐธ์กฐยทํฌ์ธํ„ฐ๊ฐ€ ๋ฌดํšจํ™”๋ฉ๋‹ˆ๋‹ค. vector์˜ reallocation๊ณผ ๊ฐ™์€ ํ•จ์ •. rehash ๊ฐ€๋Šฅ์„ฑ์ด ์žˆ๋Š” ์ƒํƒœ์—์„œ ์ด์ „ ์ดํ„ฐ๋ ˆ์ดํ„ฐ๋ฅผ ๋ณด๊ด€ยท์‚ฌ์šฉํ•˜๋ฉด UB.

Q3. โ€œload factor๋ฅผ ์ž‘๊ฒŒ ์žก์œผ๋ฉด ์–ด๋–ค trade-off๊ฐ€ ์žˆ๋‚˜์š”?โ€

๋ฉ”๋ชจ๋ฆฌ โ†‘ vs ์ถฉ๋Œ โ†“ ์˜ ํŠธ๋ ˆ์ด๋“œ์˜คํ”„์ž…๋‹ˆ๋‹ค.

max_load_factor ๊ฐ€ ์ž‘์„์ˆ˜๋ก(์˜ˆ: 0.5) ๊ฐ™์€ size์— ๋” ๋งŽ์€ bucket์„ ์œ ์ง€ํ•ฉ๋‹ˆ๋‹ค. ์ถฉ๋Œ์ด ์ค„์–ด ํ‰๊ท  lookup์ด ๋นจ๋ผ์ง€์ง€๋งŒ ๋ฉ”๋ชจ๋ฆฌ ์‚ฌ์šฉ๋Ÿ‰์ด ๋‘ ๋ฐฐ.

1
2
3
4
std::unordered_map<int, int> m;
m.max_load_factor(0.5);   // ๋ฉ”๋ชจ๋ฆฌ 2๋ฐฐ, ์ถฉ๋Œ ์ ˆ๋ฐ˜
m.reserve(10000);
// bucket_count โ‰ˆ 20000 (= 10000 / 0.5)

๋ฐ˜๋Œ€๋กœ ํฌ๊ฒŒ ์žก์œผ๋ฉด(์˜ˆ: 2.0) bucket์ด ์ ์–ด ๋ฉ”๋ชจ๋ฆฌ ์ ˆ์•ฝ. ํ•œ ๋ฒ„ํ‚ท์— ํ‰๊ท  2๊ฐœ ์›์†Œ๊ฐ€ ๋“ค์–ด๊ฐ€ ์ถฉ๋Œยท์ฒด์ธ ๊ธธ์ด ์ฆ๊ฐ€, lookup ๋А๋ ค์ง.

C++ ํ‘œ์ค€ ๊ธฐ๋ณธ์€ 1.0 โ€” ๋ฉ”๋ชจ๋ฆฌยท์„ฑ๋Šฅ ๊ท ํ˜•์ . ์‹ค๋ฌด์—์„œ๋Š” ๊ฑฐ์˜ ์•ˆ ๋ฐ”๊ฟ‰๋‹ˆ๋‹ค.

์ž‘๊ฒŒ ์žก๋Š” ๊ฒŒ ์˜๋ฏธ ์žˆ๋Š” ๊ฒฝ์šฐ:

  • hot path lookup์ด ๋งค์šฐ ๋นˆ๋ฒˆ โ€” ์ถฉ๋Œ ํ™•๋ฅ ์„ ๋” ๋‚ฎ์ถฐ ํ‰๊ท  lookup ์‹œ๊ฐ„์„ ์ค„์ž„
  • hash ํ•จ์ˆ˜์˜ ๋ถ„ํฌ๊ฐ€ ์˜์‹ฌ์Šค๋Ÿฌ์›€ โ€” ์ถฉ๋Œ์ด ๋งŽ์„ ๊ฒƒ ๊ฐ™์œผ๋ฉด ๋ฏธ๋ฆฌ ์—ฌ์œ  ํ™•๋ณด
  • ๋ฉ”๋ชจ๋ฆฌ๋Š” ์ถฉ๋ถ„, ์ง€์—ฐ์ด ๋” ์ค‘์š” โ€” ๊ฒŒ์ž„ ์„œ๋ฒ„ยท์‹ค์‹œ๊ฐ„ ๊ฑฐ๋ž˜ ์‹œ์Šคํ…œ

ํฌ๊ฒŒ ์žก๋Š” ๊ฒŒ ์˜๋ฏธ ์žˆ๋Š” ๊ฒฝ์šฐ:

  • ๋ฉ”๋ชจ๋ฆฌ๊ฐ€ ๋น ๋“ฏ โ€” ์ž„๋ฒ ๋””๋“œยท๋ชจ๋ฐ”์ผ
  • lookup์ด ๋“œ๋ฌผ๊ณ  ๋ฉ”๋ชจ๋ฆฌ ์ ˆ๊ฐ์ด ์šฐ์„  โ€” ๋ฐ์ดํ„ฐ ๋ณด๊ด€์šฉ map

๊ทธ๋Ÿฌ๋‚˜ ๋ณดํ†ต์€ max_load_factor๋ฅผ ๊ฑด๋“œ๋ฆฌ๋Š” ๊ฒƒ๋ณด๋‹ค reserve(N)์œผ๋กœ ๋ฏธ๋ฆฌ capacity ํ™•๋ณดํ•˜๋Š” ๊ฒŒ ํ›จ์”ฌ ํšจ๊ณผ์ ์ž…๋‹ˆ๋‹ค. rehash ์ž์ฒด๋ฅผ ํšŒํ”ผํ•˜๋Š” ๊ฒŒ ๊ฐ€์žฅ ํฐ ์„ฑ๋Šฅ ๊ฐœ์„ .


8. ํšŒ๊ท€ ๋‹ค๋ฆฌ

ํŒŒ์ผ์—ฐ๊ฒฐ ์ง€์ 
15_1_vector_vs_hash_concepts์ด ํŒŒ์ผ์˜ ๋ณธํŽธ โ€” hash ํ•จ์ˆ˜์˜ 3๋Œ€ ์กฐ๊ฑด(๊ท ๋“ฑ ๋ถ„ํฌยท์ผ๊ด€์„ฑยท๋น ๋ฅธ ๊ณ„์‚ฐ) ์ •๋ฆฌ
13_vector_vs_listvector์˜ reallocation๊ณผ hash์˜ rehash๊ฐ€ ๊ฐ™์€ ํŒจํ„ด โ€” capacity ์ดˆ๊ณผ ์‹œ ์ƒˆ ๋ฐฐ์—ด๋กœ ๋ณต์‚ฌ. reserve(N)์ด ๋‘˜ ๋‹ค ํ‘œ์ค€ ํšŒํ”ผ์ฑ…
14_std_mapRB-Tree ๊ธฐ๋ฐ˜ map๊ณผ์˜ ๋น„๊ต โ€” ํ•ญ์ƒ O(log N) vs ํ‰๊ท  O(1)/์ตœ์•… O(N). ์ˆœ์„œ ๋ณด์žฅ vs ๋น ๋ฅธ ํ‰๊ท  lookup
16_stl_containersSTL ํ†ตํ•ฉ ์ •๋ฆฌ โ€” unordered_* ์ปจํ…Œ์ด๋„ˆ 4์ข…(map/multimap/set/multiset) ๊ณตํ†ต ํŠน์„ฑ
23_race_conditionrehash ์ค‘ ๋‹ค๋ฅธ ์Šค๋ ˆ๋“œ๊ฐ€ lookupํ•˜๋ฉด UB. STL ์ปจํ…Œ์ด๋„ˆ๋Š” thread-safe๊ฐ€ ์•„๋‹ˆ๋ผ์„œ ๋™์‹œ ์ ‘๊ทผ ๋ณดํ˜ธ ํ•„์š” (FCriticalSection ๋“ฑ)
์ด ๊ธฐ์‚ฌ๋Š” ์ €์ž‘๊ถŒ์ž์˜ CC BY 4.0 ๋ผ์ด์„ผ์Šค๋ฅผ ๋”ฐ๋ฆ…๋‹ˆ๋‹ค.

ยฉ GoldBoll. ์ผ๋ถ€ ๊ถŒ๋ฆฌ ๋ณด์œ 

Powered by Jekyll with Chirpy theme

์ธ๊ธฐ ํƒœ๊ทธ