ํฌ์ŠคํŠธ

CS โ€” std map followup

CS โ€” std map followup

๐Ÿ“• 04/30 โ€” std::map ๋ชจ์˜๋ฉด์ ‘ ๊ผฌ๋ฆฌ์งˆ๋ฌธ ์ •๋ฆฌ

14_std_map.md ๋ชจ์˜๋ฉด์ ‘ ์งํ›„ ๋‚˜์˜จ ํ›„์† ์งˆ๋ฌธ 10๊ฐœ๋ฅผ 1:1๋กœ ์ •๋ฆฌํ•œ ๋…ธํŠธ. ๋ณธ๋ฌธ์€ 14๋ฒˆ ์›๋ณธ์˜ ํ•ด๋‹น ์„น์…˜์„ ๊ฐ€๋ฆฌํ‚ค๊ณ , ์—ฌ๊ธฐ์„œ๋Š” ๋‹ต๋ณ€๋งŒ ์งง๊ฒŒ ๊ฒฐ๋ก  โ†’ ๊ทผ๊ฑฐ โ†’ ์ฝ”๋“œ/์˜ˆ ์ˆœ์œผ๋กœ ์••์ถ•ํ•œ๋‹ค.


๋ชฉ์ฐจ

  1. ํ•ด์‹œ ์ถฉ๋Œ๋กœ ์ธํ•œ O(n) ์ŠคํŒŒ์ดํฌ ํšŒํ”ผ
  2. compare ์žฌ์ •์˜ (Custom Compare)
  3. ํ•ด์‹œ / unordered / ์ค‘๋ณตํ‚ค ํ—ˆ์šฉ
  4. Red-Black Tree ์˜ red ๊ทœ์น™
  5. AVL ์•ฝ์ž
  6. emplace ๊ฐ€ ๋ญ”๊ฐ€
  7. ํž™(heap) ์ด ๋ญ”๊ฐ€
  8. Red โ€” ์ƒˆ ๋…ธ๋“œ๋ฅผ ๋นจ๊ฐ•์œผ๋กœ ์‚ฝ์ž…ํ•˜๋Š” ๊ธฐ์ค€
  9. ์–ธ๋ฆฌ์–ผ์ด ์บ์‹œ ์นœํ™” ์šฐ์„ ์ธ ์ด์œ 
  10. Algo:: ๊ฐ€ ๋ญ”์ง€

1. ํ•ด์‹œ ์ถฉ๋Œ๋กœ ์ธํ•œ O(n) ์ŠคํŒŒ์ดํฌ ํšŒํ”ผ

ํ•œ ์ค„ ๊ฒฐ๋ก  โ€” std::unordered_map ์€ ํ‰๊ท  O(1) ์ด์ง€๋งŒ ์•…์˜์  ์ž…๋ ฅ / ๋‚˜์œ ํ•ด์‹œ ํ•จ์ˆ˜๋กœ ๋ชจ๋“  ํ‚ค๊ฐ€ ํ•œ ๋ฒ„ํ‚ท์— ๋ชฐ๋ฆฌ๋ฉด O(n) ๊นŒ์ง€ ๋–จ์–ด์ง„๋‹ค. ์ด โ€œ์ตœ์•… ๋ณด์žฅโ€์ด ํ•„์š”ํ•˜๋ฉด std::map (RB-Tree, O(log n) ์ตœ์•… ๋ณด์žฅ) ์„ ์„ ํƒํ•œ๋‹ค.

1
2
3
4
5
// ์•…์˜์  ํ•ด์‹œ โ€” ๋ชจ๋“  ํ‚ค๊ฐ€ bucket[0] ์— ์ฒด์ธ
struct BadHash { size_t operator()(int k) const { return 0; } };
std::unordered_map<int, int, BadHash> u;
for (int i = 0; i < 1000; ++i) u.insert({i, i});
u.find(999);   // O(n) โ€” 1000๋ฒˆ ๋น„๊ต

์–ธ์ œ map ์„ ์„ ํƒ?

  • ์‹ค์‹œ๊ฐ„ ์‹œ์Šคํ…œยท์„œ๋ฒ„ ๋“ฑ ๊ผฌ๋ฆฌ ์ง€์—ฐ(tail latency) ์ด ์ค‘์š”
  • ์™ธ๋ถ€ ์ž…๋ ฅ ํ‚ค(ํด๋ผ๊ฐ€ ๋ณด๋‚ธ ID, URL ๋“ฑ) โ€” ํ•ด์‹œ DoS ๋ฐฉ์–ด
  • ํ‚ค ์ •๋ ฌยท๋ฒ”์œ„ ์กฐํšŒ(lower_bound/upper_bound) ๊ฐ€ ๋™์‹œ์— ํ•„์š”

std::map ์€ ํšŒ์ „ + ์žฌ์ƒ‰์น ๋กœ ํŠธ๋ฆฌ ๋†’์ด๋ฅผ ํ•ญ์ƒ โ‰ค 2 logโ‚‚(n+1) ๋กœ ๋ฌถ์–ด ์ตœ์•…๋„ O(log n) ๋ณด์žฅ. 14๋ฒˆ ยง3-2 ์ฐธ์กฐ.


2. compare ์žฌ์ •์˜ (Custom Compare)

ํ•œ ์ค„ ๊ฒฐ๋ก  โ€” std::map ์˜ 3๋ฒˆ์งธ ํ…œํ”Œ๋ฆฟ ์ธ์ž๊ฐ€ Compare (๊ธฐ๋ณธ std::less<Key>). ์ด ์ž๋ฆฌ๋ฅผ ํ•จ์ˆ˜ ๊ฐ์ฒด / ๋žŒ๋‹ค / ํ•จ์ˆ˜ ํฌ์ธํ„ฐ๋กœ ๋ฐ”๊ฟ” ์ •๋ ฌ ๊ธฐ์ค€์„ ๊ฐˆ์•„๋‚„ ์ˆ˜ ์žˆ๋‹ค. ํ‚ค ๊ฐ์ฒด๊ฐ€ operator< ๋ฅผ ๊ฐ€์ง€๋ฉด ๋ณ„๋„ ์ž‘์—… ์—†์ด ๋™์ž‘.

2-1. ์‹œ๊ทธ๋‹ˆ์ฒ˜

1
2
3
4
template<class Key, class T,
         class Compare   = std::less<Key>,
         class Allocator = std::allocator<std::pair<const Key, T>>>
class map;

2-2. ๋‚ด๋ฆผ์ฐจ์ˆœ (std::greater)

1
2
3
std::map<int, std::string, std::greater<int>> desc;
desc[1]="one"; desc[2]="two"; desc[3]="three";
// ์ˆœํšŒ: 3 โ†’ 2 โ†’ 1

2-3. ๋žŒ๋‹ค (๋Œ€์†Œ๋ฌธ์ž ๋ฌด์‹œ ์ •๋ ฌ)

1
2
3
4
5
6
auto ci_less = [](const std::string& a, const std::string& b) {
    return std::lexicographical_compare(
        a.begin(), a.end(), b.begin(), b.end(),
        [](char ca, char cb){ return std::tolower(ca) < std::tolower(cb); });
};
std::map<std::string, int, decltype(ci_less)> m(ci_less);

2-4. ์‚ฌ์šฉ์ž ์ •์˜ ํ‚ค โ€” operator< ๋งŒ ์ •์˜ํ•˜๋ฉด ๋

1
2
3
4
5
6
7
struct Point {
    int x, y;
    bool operator<(const Point& o) const {
        return std::tie(x, y) < std::tie(o.x, o.y);   // lexicographic
    }
};
std::map<Point, std::string> places;   // Compare ์ธ์ž ์ƒ๋žต

ํŠธ๋ฆฌ๋งต์€ operator< ํ•˜๋‚˜๋กœ ์ถฉ๋ถ„. ํ•ด์‹œ๋งต์€ std::hash<K> ํŠน์ˆ˜ํ™” + operator== ๋‘˜ ๋‹ค ํ•„์š” โ†’ ํŠธ๋ฆฌ๋งต์˜ ์ž‘์€ ํŽธ์˜์„ฑ.


3. ํ•ด์‹œ / unordered / ์ค‘๋ณตํ‚ค ํ—ˆ์šฉ

3-1. โ€œํ•ด์‹œ = unorderedโ€ ์ธ ์ด์œ 

ํ•ด์‹œ ํ…Œ์ด๋ธ”์€ hash(key) % bucket_count โ†’ ๋ฒ„ํ‚ท ์ธ๋ฑ์Šค๋กœ ๋งคํ•‘ํ•œ๋‹ค. ํ‚ค โ†’ ์ •์ˆ˜ โ†’ ์Šฌ๋กฏ. ์ •์ˆ˜ ๋ชจ๋“ˆ๋กœ ๊ฒฐ๊ณผ๋Š” ํ‚ค ์›๋ณธ ์ˆœ์„œ์™€ ๋ฌด๊ด€ํ•˜๋ฏ€๋กœ, ์ˆœํšŒ ์ˆœ์„œ๋ฅผ ๋ณด์žฅํ•  ๋ฐฉ๋ฒ•์ด ์—†๋‹ค. ๊ทธ๋ž˜์„œ STL ๋„ ์ด๋ฆ„์— unordered_ ๋ฅผ ๋ถ™์˜€๋‹ค.

1
2
3
4
ํ‚ค:    "Alice", "Bob", "Carol"
ํ•ด์‹œ:  hash("Alice")=4283..., hash("Bob")=8821..., hash("Carol")=5512...
๋ฒ„ํ‚ท:  4283 % 16 = 11,  8821 % 16 = 5,  5512 % 16 = 8
์ˆœํšŒ:  bucket[5]=Bob โ†’ bucket[8]=Carol โ†’ bucket[11]=Alice  โ† ํ‚ค ์‚ฌ์ „์ˆœ X

3-2. ๊ฒŒ์ž„ ํ”„๋กœ๊ทธ๋ž˜๋ฐ์ด unordered ๋ฅผ ์„ ํ˜ธํ•˜๋Š” ์ด์œ 

14๋ฒˆ ยง9 + 13๋ฒˆ ๊ฒฐ๋ก ๊ณผ ๋™์ผ โ€” ์บ์‹œ ์นœํ™”ยทํ‰๊ท  O(1)

๊ฒŒ์ž„ ์›Œํฌ๋กœ๋“œํŠธ๋ฆฌ(map)ํ•ด์‹œ(unordered_map / TMap)
๋งค ํ”„๋ ˆ์ž„ 1000~10000 lookuplog n ร— ์บ์‹œ ๋ฏธ์Šค ๋น„์‹ธ๋‹คํ‰๊ท  1๋ฒˆ hit, ์บ์‹œ ์นœํ™”
ํ‚ค ์ •๋ ฌ ๊ฑฐ์˜ ์•ˆ ์”€๊ฐ•์  ๋ฌด์šฉ์†์‹ค ์—†์Œ
์ตœ์•… ๋ณด์žฅ vs ํ‰๊ท  ์ฒ˜๋ฆฌ๋Ÿ‰์ตœ์•… ๋ณด์žฅํ‰๊ท  ์ฒ˜๋ฆฌ๋Ÿ‰ โ†‘ โ˜…
๋ฉ”๋ชจ๋ฆฌ ์ง€์—ญ์„ฑ๋…ธ๋“œ ๋ถ„์‚ฐ(ํž™)์Šฌ๋กฏ ๋ฐฐ์—ด ์ธ์ ‘

Unreal TMap ์€ ๋” ๋‚˜์•„๊ฐ€ ์ฒด์ด๋‹ ๋Œ€์‹  open addressing ์„ ์จ์„œ ์บ์‹œ ์นœํ™”์„ฑ์„ ํ•œ ๋‹จ๊ณ„ ๋” ์˜ฌ๋ ธ๋‹ค (14๋ฒˆ ยง9-6).

3-3. โ€œํ•ด์‹œ์ผ ๋•Œ ์ค‘๋ณตํ‚ค ํ—ˆ์šฉ?โ€

๋‹จ์ผ ํ‚ค์ค‘๋ณต ํ‚ค
std::unordered_map<K,V>std::unordered_multimap<K,V>
std::unordered_set<K>std::unordered_multiset<K>
Unreal TMap<K,V>Unreal TMultiMap<K,V>
  • ๋‹จ์ผ ํ‚ค ์ปจํ…Œ์ด๋„ˆ๋Š” ์ค‘๋ณต ๋ถˆ๊ฐ€ โ€” ํ•ด์‹œ์ด๋“  ํŠธ๋ฆฌ์ด๋“  ๋™์ผ.
  • ์ค‘๋ณต์„ ํ—ˆ์šฉํ•˜๋ ค๋ฉด multi* / TMultiMap ์„ ๋ช…์‹œ์ ์œผ๋กœ ์„ ํƒ.
  • ์ค‘๋ณต ์‹œ equal_range (STL) / MultiFind (Unreal) ๋กœ ๊ฐ™์€ ํ‚ค์˜ ๋ชจ๋“  ๊ฐ’์„ ๋ฌถ์–ด ๊ฐ€์ ธ์˜ด.
1
2
3
4
5
std::unordered_multimap<std::string, int> scores;
scores.insert({"Alice", 85});
scores.insert({"Alice", 92});
scores.insert({"Alice", 78});
auto [from, to] = scores.equal_range("Alice");

C++11 ์ดํ›„ multi* ์ปจํ…Œ์ด๋„ˆ๋Š” ์‚ฝ์ž… ์ˆœ์„œ ์•ˆ์ •์„ฑ(stability) ๋„ ๋ณด์žฅ โ€” ๊ฐ™์€ ํ‚ค ์•ˆ์—์„œ ๋จผ์ € ๋„ฃ์€ ๊ฒŒ ๋จผ์ € ๋‚˜์˜จ๋‹ค.


4. Red-Black Tree ์˜ red ๊ทœ์น™

ํ•œ ์ค„ ๊ฒฐ๋ก  โ€” RB-Tree ์˜ ์ƒ‰๊น”์€ 5๊ฐ€์ง€ ์†์„ฑ์„ ๋™์‹œ์— ๋งŒ์กฑํ•ด์•ผ ํ•œ๋‹ค. ๋นจ๊ฐ•์€ ๊ทธ์ค‘ 4๋ฒˆ(์—ฐ์† ๊ธˆ์ง€)๊ณผ 5๋ฒˆ(black height ์ผ์ •) ์˜ ํ•ต์‹ฌ ๋ณ€์ˆ˜.

1
2
3
4
5
1) ๋ชจ๋“  ๋…ธ๋“œ๋Š” ๋นจ๊ฐ• ๋˜๋Š” ๊ฒ€์ •
2) ๋ฃจํŠธ๋Š” ๊ฒ€์ •
3) ๋ชจ๋“  NIL (๋ฆฌํ”„) ์€ ๊ฒ€์ •
4) ๋นจ๊ฐ• ๋…ธ๋“œ์˜ ์ž์‹์€ ๋ฐ˜๋“œ์‹œ ๊ฒ€์ •      โ† ๋นจ๊ฐ• ์—ฐ์†(R-R) ๊ธˆ์ง€
5) ์ž„์˜ ๋…ธ๋“œ โ†’ ํ›„์† NIL ๊นŒ์ง€ ๊ฒฝ๋กœ์˜ ๊ฒ€์ • ๋…ธ๋“œ ์ˆ˜ ๋™์ผ (black height)

4-1. โ€œredโ€ ๋งŒ ๋”ฐ๋กœ ๋ณด๋ฉด ๋‘ ๊ฐ€์ง€ ๊ทœ์น™

  • R-R ๊ธˆ์ง€ (์†์„ฑ 4) โ€” ๋นจ๊ฐ• ๋‘ ๊ฐœ๊ฐ€ ๋ถ€๋ชจ-์ž์‹์œผ๋กœ ์ด์–ด์ง€๋ฉด ์œ„๋ฐ˜. ์‚ฝ์ž…ยท์‚ญ์ œ ํ›„ ํšŒ์ „ยท์žฌ์ƒ‰์น ๋กœ ์ฆ‰์‹œ ๋ณต๊ตฌ.
  • ์‚ฝ์ž… ์‹œ ์ƒˆ ๋…ธ๋“œ = ๋นจ๊ฐ• (๊ด€ํ–‰) โ€” ๊ฒ€์ •์œผ๋กœ ๋„ฃ์œผ๋ฉด black height ๊ฐ€ ๊นจ์ ธ ๋ณต๊ตฌ๊ฐ€ ๋” ๋น„์‹ธ๋‹ค โ†’ ํ•ญ์ƒ ๋นจ๊ฐ•. ์ž์„ธํ•œ ์ด์œ ๋Š” ยง8.

4-2. R-R ์œ„๋ฐ˜ ๋ณต๊ตฌ ํ๋ฆ„ (์‚ฝ์ž…)

1
2
3
๋ถ€๋ชจ๊ฐ€ ๊ฒ€์ •     โ†’ ๋ (์œ„๋ฐ˜ ์—†์Œ)
๋ถ€๋ชจ๊ฐ€ ๋นจ๊ฐ• + ์‚ผ์ดŒ๋„ ๋นจ๊ฐ• โ†’ ์žฌ์ƒ‰์น  (ํ• ์•„๋ฒ„์ง€ ๋นจ๊ฐ•, ์œ„๋กœ ์ „ํŒŒ)
๋ถ€๋ชจ๊ฐ€ ๋นจ๊ฐ• + ์‚ผ์ดŒ์ด ๊ฒ€์ • โ†’ ํšŒ์ „ + ์žฌ์ƒ‰์น  (LL/LR/RR/RL 4์ผ€์ด์Šค)

์‚ฝ์ž… ์‹œ ํšŒ์ „์€ ์ตœ๋Œ€ 2ํšŒ, ์‚ญ์ œ ์‹œ ์ตœ๋Œ€ 3ํšŒ๋กœ ๋๋‚œ๋‹ค (14๋ฒˆ ยง3-3, ยง3-4).


5. AVL ์•ฝ์ž

Adelson-Velsky and Landis โ€” 1962๋…„ RB ํŠธ๋ฆฌ๋ณด๋‹ค ๋จผ์ € ๊ณ ์•ˆํ•œ ์ž๊ธฐ ๊ท ํ˜• BST. ๋ฐœ๋ช…์ž ๋‘ ์‚ฌ๋žŒ์˜ ์ด๋ฆ„์„ ๊ทธ๋Œ€๋กœ ๋•„๋‹ค.

ย RB-TreeAVL Tree
๊ท ํ˜• ์กฐ๊ฑด์ƒ‰๊น” 5์†์„ฑ๋ชจ๋“  ๋…ธ๋“œ ์ขŒ์šฐ ๋†’์ด ์ฐจ โ‰ค 1
ํŠธ๋ฆฌ ๋†’์ดโ‰ค 2 log(n+1)โ‰ค 1.44 log(n+2)
๊ฒ€์ƒ‰์•ฝ๊ฐ„ ๋А๋ฆผ์•ฝ๊ฐ„ ๋น ๋ฆ„
์‚ฝ์ž… ํšŒ์ „์ตœ๋Œ€ 2ํšŒ์ตœ๋Œ€ 1ํšŒ์ง€๋งŒ ์œ„๋กœ ์ „ํŒŒ
์‚ญ์ œ ํšŒ์ „์ตœ๋Œ€ 3ํšŒ์ตœ๋Œ€ O(log n) ํšŒ
๋ฉ”๋ชจ๋ฆฌ์ƒ‰ 1๋น„ํŠธ๋†’์ด ์ •๋ณด ~4B
์ฑ„ํƒ์ฒ˜STL map/set, Linux CFS, Java TreeMapDB ์ธ๋ฑ์Šค(์ „ํ†ต)

์•”๊ธฐ ํŒจํ„ด: ๊ฒ€์ƒ‰ โ‰ซ ๊ฐฑ์‹  โ†’ AVL / ๊ฐฑ์‹ ๋„ ์ž์ฃผ โ†’ RB / ๋ฒ”์šฉ โ†’ RB. STL ์ด RB ๋ฅผ ์„ ํƒํ•œ ์ด์œ ๋Š” โ€œ๊ฐฑ์‹ ๋„ ํ”ํ•œ ๋ฒ”์šฉ ์ปจํ…Œ์ด๋„ˆโ€ ๋ผ์„œ.


6. emplace ๊ฐ€ ๋ญ”๊ฐ€

ํ•œ ์ค„ ๊ฒฐ๋ก  โ€” emplace(args...) ๋Š” ์ปจํ…Œ์ด๋„ˆ์˜ ๋…ธ๋“œ ์•ˆ์—์„œ ์ง์ ‘ ๊ฐ์ฒด๋ฅผ ์ƒ์„ฑํ•œ๋‹ค. ์ž„์‹œ ๊ฐ์ฒด๋ฅผ ๋งŒ๋“ค์ง€ ์•Š์œผ๋ฏ€๋กœ ๋ณต์‚ฌ/์ด๋™ ๋น„์šฉ์„ ์ค„์ด๊ณ , ๋ฌด๋ธŒ-์˜จ๋ฆฌ ํƒ€์ž…(unique_ptr) ๋„ ๊น”๋”ํžˆ ๋‹ด์„ ์ˆ˜ ์žˆ๋‹ค.

6-1. insert / emplace / operator[] ๋น„๊ต

1
2
3
4
5
6
7
8
9
10
std::map<std::string, std::vector<int>> m;

// 1) operator[] โ€” default ์ƒ์„ฑ ํ›„ ๋Œ€์ž… (2๋‹จ๊ณ„)
m["A"] = std::vector<int>{1,2,3};

// 2) insert โ€” ์ž„์‹œ pair ์ƒ์„ฑ
m.insert({"B", std::vector<int>{4,5,6}});

// 3) emplace โ€” pair ์ธ์ž๋ฅผ ๋ฐ›์•„ ๋…ธ๋“œ ์•ˆ์—์„œ in-place ์ƒ์„ฑ โ˜…
m.emplace("C", std::vector<int>{7,8,9});

6-2. C++17 ์˜ ๋‘ ํ˜•์ œ

ํ•จ์ˆ˜ํ‚ค ์žˆ์„ ๋•Œํ‚ค ์—†์„ ๋•ŒํŠน์ง•
emplace(k, args...)๋ฌด์‹œ (์ธ์ž๋Š” ์ด๋ฏธ ํ‰๊ฐ€๋จ)๋…ธ๋“œ in-place ์ƒ์„ฑํ‘œ์ค€ emplace
try_emplace(k, args...)์ธ์ž ์ž์ฒด๋ฅผ ๋งŒ๋“ค์ง€ ์•Š์Œ โ˜…๋…ธ๋“œ in-place ์ƒ์„ฑunique_ptr ์•ˆ์ „
insert_or_assign(k, v)๊ธฐ์กด ๊ฐ’์— ๋Œ€์ž…์ƒˆ๋กœ ์‚ฝ์ž…์˜๋„ ๋ช…ํ™• (operator[] ํŠธ๋žฉ ํšŒํ”ผ)

6-3. try_emplace + unique_ptr ํŒจํ„ด

1
2
3
4
5
6
7
8
std::map<std::string, std::unique_ptr<Resource>> resources;

// operator[] ํ•จ์ •: ์ด๋ฏธ ์žˆ์œผ๋ฉด ๊ธฐ์กด unique_ptr ํŒŒ๊ดด
resources["key1"] = std::make_unique<Resource>("data1");

// try_emplace: ํ‚ค ์žˆ์œผ๋ฉด make_unique ํ˜ธ์ถœ์กฐ์ฐจ ์•ˆ ํ•จ โ˜…
auto [it, inserted] = resources.try_emplace("key1",
    std::make_unique<Resource>("data1"));

๋ฉด์ ‘ ๋‹จ๊ณจ โ€” โ€œoperator[] ์™€ emplace ์ฐจ์ด?โ€ โ†’ ์ž„์‹œ ๊ฐ์ฒด + default ์‚ฝ์ž… ํŠธ๋žฉ โ†’ try_emplace / insert_or_assign ์œผ๋กœ ์ •๋ฆฌ. 14๋ฒˆ ยง7-4ยทยง7-5 ์›๋ณธ.


7. ํž™(heap) ์ด ๋ญ”๊ฐ€

๋ฉด์ ‘ ๋งฅ๋ฝ์— ๋”ฐ๋ผ ๋‘ ๊ฐ€์ง€ ์˜๋ฏธ๊ฐ€ ์„ž์ด๋ฏ€๋กœ ํ•ญ์ƒ ๋‘˜ ๋‹ค ๋‹ตํ•ด ๋‘”๋‹ค.

7-1. ๋ฉ”๋ชจ๋ฆฌ ์˜์—ญ์œผ๋กœ์„œ์˜ ํž™

์˜์—ญํ• ๋‹น ์‹œ์ ํ•ด์ œ ์‹œ์ ๋น„๊ณ 
์Šคํƒํ•จ์ˆ˜ ์ง„์ž…ํ•จ์ˆ˜ ์ข…๋ฃŒ (RAII)๋น ๋ฆ„, ํฌ๊ธฐ ์ œํ•œ
ํž™(heap)new / mallocdelete / free๋А๋ฆผ, ํฌ๊ธฐ ํผ, ๋‹จํŽธํ™”
์ •์ /์ „์—ญํ”„๋กœ๊ทธ๋žจ ์‹œ์ž‘์ข…๋ฃŒstatic, ์ „์—ญ ๋ณ€์ˆ˜

std::map / std::list / std::unordered_map ์ด ๋…ธ๋“œ๋ฅผ ํž™์— ๋ถ„์‚ฐ ํ• ๋‹น ํ•˜๋Š” ์ด์œ  โ€” ๋…ธ๋“œ ํฌ๊ธฐ๊ฐ€ ๊ฐ€๋ณ€์ด๊ณ , iterator ์•ˆ์ •์„ฑ์„ ์œ„ํ•ด ๋…ธ๋“œ ์ฃผ์†Œ๊ฐ€ ๊ณ ์ •๋ผ์•ผ ํ•˜๊ธฐ ๋•Œ๋ฌธ. ๊ทธ ๋Œ€๊ฐ€๋กœ ์บ์‹œ ์ ๋Œ€์ .

1
2
3
std::map<int,int> m;
// ๋…ธ๋“œ 1๊ฐœ โ‰ˆ color(8) + parent(8) + left(8) + right(8) + pair(int+int+pad)(12) + heap header(~16)
//        โ‰ˆ 60๋ฐ”์ดํŠธ โ†’ ๋ฐ์ดํ„ฐ 8B ์œ„ํ•ด 60B โ†’ ํšจ์œจ ~13%

7-2. ์ž๋ฃŒ๊ตฌ์กฐ๋กœ์„œ์˜ ํž™

๋ถ€๋ชจ โ‰ฅ ์ž์‹(max-heap) / ๋ถ€๋ชจ โ‰ค ์ž์‹(min-heap) ์ธ ์™„์ „ ์ด์ง„ ํŠธ๋ฆฌ. STL std::priority_queue ์˜ ๋‚ด๋ถ€ ๊ตฌ์กฐ์ด๋ฉฐ ๋ณดํ†ต std::vector ๋ฐฐ์—ด ์œ„์— ์ธ๋ฑ์Šค๋กœ ํ‘œํ˜„ (์บ์‹œ ์นœํ™”).

์—ฐ์‚ฐ๋ณต์žก๋„
pushO(log n)
pop (top ์ œ๊ฑฐ)O(log n)
topO(1)

๊ฒŒ์ž„์—์„œ๋Š” A* ๊ธธ์ฐพ๊ธฐ์˜ open list, ์ด๋ฒคํŠธ ํƒ€์ด๋จธ ํ, ์šฐ์„ ์ˆœ์œ„ ์ž‘์—… ํ ๋“ฑ์— ์“ฐ์ž„.


8. Red โ€” ์ƒˆ ๋…ธ๋“œ๋ฅผ ๋นจ๊ฐ•์œผ๋กœ ์‚ฝ์ž…ํ•˜๋Š” ๊ธฐ์ค€

ํ•œ ์ค„ ๊ฒฐ๋ก  โ€” black height ๋ณ€ํ™”๋ฅผ 0์œผ๋กœ ๋งŒ๋“ค๊ธฐ ์œ„ํ•ด์„œ. ๊ฒ€์ •์œผ๋กœ ๋„ฃ์œผ๋ฉด ๊ทธ ๊ฒฝ๋กœ black height ๊ฐ€ 1 ๋Š˜์–ด ์†์„ฑ 5(๋ชจ๋“  ๊ฒฝ๋กœ ๊ฒ€์ • ์ˆ˜ ๋™์ผ) ๊ฐ€ ๊นจ์ง€๊ณ , ๋‹ค๋ฅธ ๋ชจ๋“  ๊ฒฝ๋กœ๋ฅผ ๋งž์ถฐ์•ผ ํ•ด์„œ ๋น„์‹ธ๋‹ค. ๋นจ๊ฐ•์œผ๋กœ ๋„ฃ์œผ๋ฉด ์œ„๋ฐ˜ ๊ฐ€๋Šฅ์„ฑ์€ ์†์„ฑ 4(R-R ๊ธˆ์ง€) ํ•œ ๊ฐ€์ง€๋กœ ๊ตญํ•œ๋˜๊ณ  ํšŒ์ „ยท์žฌ์ƒ‰์น ๋กœ ๊ตญ์†Œ ๋ณต๊ตฌ๋œ๋‹ค.

1
2
3
4
5
6
7
8
9
๊ฒ€์ • ์‚ฝ์ž… ์‹œ:
  โ†’ ๊ทธ ๊ฒฝ๋กœ black height +1
  โ†’ ์†์„ฑ 5 ์œ„๋ฐ˜ (๋ชจ๋“  ๊ฒฝ๋กœ์˜ black height ๋™์ผํ•ด์•ผ ํ•จ)
  โ†’ ๋‹ค๋ฅธ ๋ชจ๋“  ๊ฒฝ๋กœ์—๋„ black height ๋งž์ถ”๊ธฐ โ†’ ์ „์ฒด ํŠธ๋ฆฌ ์†๋ด์•ผ ํ•จ

๋นจ๊ฐ• ์‚ฝ์ž… ์‹œ:
  โ†’ black height ๋ณ€ํ™” ์—†์Œ (์†์„ฑ 5 ์œ ์ง€)
  โ†’ ์œ„๋ฐ˜ ๊ฐ€๋Šฅ์„ฑ์€ ์†์„ฑ 4 (R-R) ๋ฟ
  โ†’ ๋ถ€๋ชจ๊ฐ€ ๊ฒ€์ •์ด๋ฉด ๋, ๋นจ๊ฐ•์ด๋ฉด ํšŒ์ „ยท์žฌ์ƒ‰์น ๋กœ ๊ตญ์†Œ ๋ณต๊ตฌ

๋ณต๊ตฌ ๋ถ„๊ธฐ (์‚ฝ์ž… ํ›„):

1
2
3
parent.color == BLACK              โ†’ ๋
parent.color == RED, uncle == RED  โ†’ ์žฌ์ƒ‰์น  (ํ• ์•„๋ฒ„์ง€ ๋นจ๊ฐ•, ์œ„๋กœ ์ „ํŒŒ)
parent.color == RED, uncle == BLACK โ†’ ํšŒ์ „ + ์žฌ์ƒ‰์น  (LL/LR/RR/RL)

์‚ฝ์ž… ์‹œ ํšŒ์ „์€ ์ตœ๋Œ€ 2ํšŒ โ€” RB ๊ฐ€ AVL ๋ณด๋‹ค ๊ฐฑ์‹  ๋น„์šฉ์ด ์ ์€ ๊ฒฐ์ •์  ์ด์œ .


9. ์–ธ๋ฆฌ์–ผ์ด ์บ์‹œ ์นœํ™” ์šฐ์„ ์ธ ์ด์œ 

ํ•œ ์ค„ ๊ฒฐ๋ก  โ€” ๊ฒŒ์ž„ ์—”์ง„์€ ๋งค ํ”„๋ ˆ์ž„ 16.6ms (60fps) / 8.3ms (120fps) ๋ผ๋Š” ์ ˆ๋Œ€ ์‹œ๊ฐ„ ์˜ˆ์‚ฐ์ด ์žˆ๊ณ , ๊ฐ™์€ ์ž๋ฃŒ์— ๋Œ€ํ•ด ์ˆ˜๋งŒ ๋ฒˆ lookupยทiterate ๊ฐ€ ์ผ์–ด๋‚œ๋‹ค. ํŠธ๋ฆฌยท์—ฐ๊ฒฐ ๋ฆฌ์ŠคํŠธ์˜ ๋…ธ๋“œ ๋ถ„์‚ฐ์€ ์บ์‹œ ๋ฏธ์Šค๋ฅผ ์–‘์‚ฐํ•ด frame budget ์„ ๊ฐ‰์•„๋จน๋Š”๋‹ค.

9-1. 1๊ธ‰ ์‹œ๋ฏผ ์ปจํ…Œ์ด๋„ˆ

์นดํ…Œ๊ณ ๋ฆฌSTLUnreal๋น„๊ณ 
์‹œํ€€์Šคstd::vectorTArray โ˜…์—ฐ์† ๋ฐฐ์—ด
ํ•ด์‹œ ๋งตstd::unordered_mapTMap โ˜…open addressing (์ฒด์ด๋‹ X)
ํ•ด์‹œ ์…‹std::unordered_setTSet โ˜…ย 
์ •๋ ฌ ๋งต (RB-Tree)std::map(์—†์Œ)TSortedMap ์œผ๋กœ ๋Œ€์ฒด
์—ฐ๊ฒฐ ๋ฆฌ์ŠคํŠธstd::listTLinkedList (๋ณด์กฐ)๊ฑฐ์˜ ์•ˆ ์”€

9-2. TSortedMap ๋„ RB ๊ฐ€ ์•„๋‹ˆ๋‹ค

๋‚ด๋ถ€๋Š” ์ •๋ ฌ๋œ TArray + ์ด์ง„ ํƒ์ƒ‰. ์ž‘์€ N ์—์„œ๋Š” RB-Tree ๋ณด๋‹ค ์บ์‹œ ์นœํ™”์ ์ด๊ณ , ํฐ N ์—์„œ๋„ ํŠธ๋ฆฌ ๋…ธ๋“œ 60B/์›์†Œ 8B ๊ฐ™์€ ์˜ค๋ฒ„ํ—ค๋“œ๋ฅผ ํ”ผํ•œ๋‹ค.

9-3. TMap ์˜ open addressing

std::unordered_map ์€ ์ถฉ๋Œ ์‹œ ๋…ธ๋“œ๋ฅผ next ํฌ์ธํ„ฐ๋กœ ์ฒด์ด๋‹ โ†’ ๋…ธ๋“œ๊ฐ€ ํž™์— ๋ถ„์‚ฐ. TMap ์€ ๋ฒ„ํ‚ท ์Šฌ๋กฏ ๋ฐฐ์—ด์—์„œ ๋‹ค์Œ ์Šฌ๋กฏ์œผ๋กœ probing โ†’ ์ธ์ ‘ ๋ฉ”๋ชจ๋ฆฌ hit ์œผ๋กœ ์บ์‹œ ์นœํ™”.

9-4. UPROPERTY / GC ํ†ตํ•ฉ

1
2
3
4
5
6
7
UCLASS()
class AInventory : public AActor {
    GENERATED_BODY()
public:
    UPROPERTY()
    TMap<FName, UItem*> Items;   // GC ๊ฐ€ value UObject ์ž๋™ ์ถ”์ 
};

std::map<FName, UItem*> ์€ GC ๊ฐ€ ์ถ”์  ๋ชป ํ•ด ์–ธ๋ฆฌ์–ผ์—์„œ๋Š” ์ ˆ๋Œ€ ์‚ฌ์šฉ X. ์บ์‹œ ์นœํ™” + GC ํ†ตํ•ฉ ๋‘ ๊ฐ€์ง€๊ฐ€ TMap/TArray/TSet ์„ 1๊ธ‰ ์‹œ๋ฏผ์œผ๋กœ ๋งŒ๋“  ์ด์œ .

13๋ฒˆ์—์„œ ๋ณธ std::list ํšŒํ”ผ, 14๋ฒˆ์—์„œ ๋ณธ std::map ํšŒํ”ผ โ€” โ€œ๋ถ„์‚ฐ ๋…ธ๋“œ ์ž๋ฃŒ๊ตฌ์กฐ ํšŒํ”ผโ€ ๊ฐ€ ์ผ๊ด€๋œ ๊ฒŒ์ž„ ์—”์ง„ ์ฒ ํ•™.


10. Algo:: ๊ฐ€ ๋ญ”์ง€

ํ•œ ์ค„ ๊ฒฐ๋ก  โ€” Unreal ์˜ ์•Œ๊ณ ๋ฆฌ์ฆ˜ ๋„ค์ž„์ŠคํŽ˜์ด์Šค. STL <algorithm> ์˜ std::sort / std::find / std::binary_search ๋“ฑ๊ณผ 1:1 ๋Œ€์‘๋˜๋Š” ํ•จ์ˆ˜๋“ค์ด Algo:: ์•„๋ž˜ ์žˆ๋‹ค. TArray ์œ„์—์„œ STL ์•Œ๊ณ ๋ฆฌ์ฆ˜๊ณผ ๊ฐ™์€ ํŒจํ„ด์œผ๋กœ ์ •๋ ฌยทํƒ์ƒ‰ยท๋ณ€ํ™˜์„ ์ˆ˜ํ–‰ํ•œ๋‹ค.

10-1. ์ž์ฃผ ์“ฐ๋Š” ํ•จ์ˆ˜

Algo::STL ๋Œ€์‘์šฉ๋„
Algo::Sortstd::sort๋น„๊ต ์ •๋ ฌ (introsort)
Algo::StableSortstd::stable_sort์•ˆ์ • ์ •๋ ฌ
Algo::BinarySearchstd::binary_search์ •๋ ฌ๋œ ๋ฐฐ์—ด ํƒ์ƒ‰
Algo::BinarySearchBy(lambda ํ‚ค ์ถ”์ถœ)ํ‚ค ์ถ”์ถœ ๋žŒ๋‹ค๋กœ ํƒ์ƒ‰
Algo::Findstd::find์„ ํ˜• ํƒ์ƒ‰
Algo::FindBystd::find_if์ˆ ์–ด ํƒ์ƒ‰
Algo::Reversestd::reverse๋’ค์ง‘๊ธฐ
Algo::Transformstd::transform์‚ฌ์ƒ
Algo::Accumulatestd::accumulate๋ˆ„์ 
Algo::AllOf / AnyOf / NoneOf๋™๋ช… STL์ˆ ์–ด ๊ฒ€์‚ฌ

10-2. ์ฝ”๋“œ ์˜ˆ โ€” TArray ์ •๋ ฌ + ์ด์ง„ ํƒ์ƒ‰

1
2
3
4
5
6
7
8
9
10
11
12
TArray<TPair<FString, int32>> Pairs;
Pairs.Add({"Alice", 30});
Pairs.Add({"Bob",   25});

// ํ‚ค ๊ธฐ์ค€ ์ •๋ ฌ
Algo::Sort(Pairs, [](const auto& A, const auto& B){
    return A.Key < B.Key;
});

// ํ‚ค ์ถ”์ถœ ๋žŒ๋‹ค๋กœ ์ด์ง„ ํƒ์ƒ‰
auto Idx = Algo::BinarySearchBy(Pairs, FString("Alice"),
    [](const auto& P){ return P.Key; });

10-3. TArray::Sort ์™€ ์ฐจ์ด

TArray::Sort() ๋Š” ๋ฉค๋ฒ„ ํ•จ์ˆ˜๋กœ ๊ฐ™์€ ์ผ์„ ํ•œ๋‹ค. Algo:: ๋Š” ์ž„์˜์˜ range/iterator ํŽ˜์–ด๋ฅผ ๋ฐ›๋Š” ์ž์œ  ํ•จ์ˆ˜๋ผ STL ์Šคํƒ€์ผ ์ฝ”๋“œ๋ฅผ ์ž‘์„ฑํ•˜๊ธฐ ์ข‹๊ณ , TArray ๊ฐ€ ์•„๋‹Œ ๋‹ค๋ฅธ ์ปจํ…Œ์ด๋„ˆ์—๋„ ์“ธ ์ˆ˜ ์žˆ๋‹ค.

์ •๋ ฌ๋œ TArray + Algo::BinarySearchBy = ์‚ฌ์‹ค์ƒ TSortedMap ์˜ ๋‚ด๋ถ€ ๊ตฌ์กฐ. 14๋ฒˆ ยง9-7 ์›๋ณธ.


11. ํ•ด์‹œ(Hash) ๊ฐ€ ๋ญ”๊ฐ€ / ๋ฒ„ํ‚ท(Bucket) ์ด ๋ญ”๊ฐ€

ํ•œ ์ค„ ๊ฒฐ๋ก  โ€” ํ•ด์‹œ ํ•จ์ˆ˜๋Š” ์ž„์˜์˜ ํ‚ค(๋ฌธ์ž์—ดยท์ •์ˆ˜ยท๊ตฌ์กฐ์ฒด)๋ฅผ ๊ณ ์ • ํฌ๊ธฐ ์ •์ˆ˜๋กœ ๋ฐ”๊พธ๋Š” ํ•จ์ˆ˜. ๋ฒ„ํ‚ท์€ ํ•ด์‹œ๊ฐ’์œผ๋กœ ์ธ๋ฑ์‹ฑ๋˜๋Š” ์Šฌ๋กฏ(๋ฐฐ์—ด ์นธ). ํ•ด์‹œํ…Œ์ด๋ธ”์€ ๋ฒ„ํ‚ท = hash(key) % bucket_count ํ•œ ์ค„๋กœ ํ‚คโ†’์Šฌ๋กฏ ๋งคํ•‘์„ ๋งŒ๋“ ๋‹ค.

11-1. ํ•ด์‹œ ํ•จ์ˆ˜์˜ 3๊ฐ€์ง€ ์š”๊ฑด

์š”๊ฑด์˜๋ฏธ์œ„๋ฐ˜ ์‹œ
๊ฒฐ์ •์„ฑ๊ฐ™์€ ํ‚ค โ†’ ํ•ญ์ƒ ๊ฐ™์€ ํ•ด์‹œ๊ฐ’find ๊ฐ€ ๋ง๊ฐ€์ง
๊ท ๋“ฑ ๋ถ„ํฌํ‚ค๋“ค์ด ์ •์ˆ˜ ๊ณต๊ฐ„์— ๊ณจ๊ณ ๋ฃจ ํฉ๋ฟŒ๋ ค์ง์ถฉ๋Œ ํญ์ฆ โ†’ O(n)
๋น ๋ฆ„O(1) ์— ๊ฐ€๊น๊ฒŒ ๊ณ„์‚ฐํ‰๊ท  O(1) ๊นจ์ง
1
2
3
4
5
6
7
8
9
10
// std::hash ํŠน์ˆ˜ํ™” โ€” ์‚ฌ์šฉ์ž ์ •์˜ ํƒ€์ž…์— ํ•ด์‹œ ๋ถ€์—ฌ
struct Point { int x, y; };
namespace std {
    template<> struct hash<Point> {
        size_t operator()(const Point& p) const noexcept {
            return hash<int>{}(p.x) ^ (hash<int>{}(p.y) << 1);
        }
    };
}
std::unordered_map<Point, int> m;   // ์ด์ œ ์‚ฌ์šฉ ๊ฐ€๋Šฅ

11-2. ๋ฒ„ํ‚ท = ํ•ด์‹œ ํ…Œ์ด๋ธ”์˜ ์Šฌ๋กฏ

1
2
3
4
5
6
7
ํ‚ค:        "Alice"      "Bob"        "Carol"
hash():    4283950122   8821445190   5512330847
% 16:      11            5            8
                โ†“             โ†“             โ†“
buckets[16] = [_, _, _, _, _, Bob, _, _, Carol, _, _, Alice, _, _, _, _]
                              โ†‘             โ†‘                โ†‘
                              bucket 5      bucket 8         bucket 11
  • bucket_count โ€” ๋ฒ„ํ‚ท ๋ฐฐ์—ด ํฌ๊ธฐ (๋ณดํ†ต 2์˜ ๊ฑฐ๋“ญ์ œ๊ณฑ์ด๋‚˜ ์†Œ์ˆ˜ ๊ทผ์ฒ˜)
  • bucket(key) โ€” ํ‚ค๊ฐ€ ๋“ค์–ด๊ฐ€๋Š” ๋ฒ„ํ‚ท ์ธ๋ฑ์Šค ๋ฐ˜ํ™˜ (u.bucket("Alice") โ†’ 11)
  • bucket_size(n) โ€” n๋ฒˆ ๋ฒ„ํ‚ท์— ๋‹ด๊ธด ์›์†Œ ์ˆ˜ (์ถฉ๋Œ ์ง„๋‹จ์šฉ)

11-3. ์ถฉ๋Œ = ๋‹ค๋ฅธ ํ‚ค๊ฐ€ ๊ฐ™์€ ๋ฒ„ํ‚ท

1
2
hash("foo") % 16 = 5
hash("xyz") % 16 = 5    โ† ๋‹ค๋ฅธ ํ‚ค์ธ๋ฐ ๊ฐ™์€ ๋ฒ„ํ‚ท โ†’ ์ถฉ๋Œ

ํ•ด๊ฒฐ ๋ฐฉ๋ฒ• ๋‘ ๊ฐ€์ง€:

๋ฐฉ์‹๋™์ž‘STLUnreal
Separate Chaining๊ฐ™์€ ๋ฒ„ํ‚ท ์›์†Œ๋ฅผ ์—ฐ๊ฒฐ ๋ฆฌ์ŠคํŠธ๋กœ ๋ฌถ์Œstd::unordered_map(์•ˆ ์”€)
Open Addressing์ถฉ๋Œ ์‹œ ๋‹ค์Œ ๋นˆ ์Šฌ๋กฏ์œผ๋กœ probing(์•ˆ ์”€)TMap โ˜…

์ฒด์ด๋‹์€ ๋…ธ๋“œ๊ฐ€ ํž™์— ๋ถ„์‚ฐ โ†’ ์บ์‹œ ์ ๋Œ€์ . open addressing ์€ ๊ฐ™์€ ๋ฐฐ์—ด ์•ˆ์—์„œ ๋‹ค์Œ ์Šฌ๋กฏ โ†’ ์บ์‹œ ์นœํ™”. ๊ทธ๋ž˜์„œ TMap ์ด std::unordered_map ๋ณด๋‹ค ๊ฒŒ์ž„์—์„œ ๋น ๋ฅด๋‹ค (14๋ฒˆ ยง9-6).

11-4. ์ข‹์€ ํ•ด์‹œ ํ•จ์ˆ˜์˜ ์กฐ๊ฑด

1
2
3
4
5
6
7
// ๋‚˜์œ ํ•ด์‹œ โ€” ๋ชจ๋“  ์ •์ˆ˜๊ฐ€ ๊ฐ™์€ ๊ฐ’
struct BadHash { size_t operator()(int) const { return 42; } };
//   โ†’ ๋ชจ๋“  ํ‚ค๊ฐ€ bucket[42 % N] ํ•œ ๊ณณ์— ๋ชฐ๋ฆผ โ†’ O(n)

// ์ข‹์€ ํ•ด์‹œ โ€” ๊ท ๋“ฑ ๋ถ„ํฌ + ๋น ๋ฆ„
//   std::hash<int> ๋Š” ๋ณดํ†ต ํ•ญ๋“ฑํ•จ์ˆ˜์— ๊ฐ€๊น๊ณ  (k ์ž์ฒด)
//   std::hash<std::string> ์€ FNV-1a / MurmurHash ๋“ฑ ์‚ฌ์šฉ

์•…์˜์  ์ž…๋ ฅ์ด ๊ฐ€๋Šฅํ•œ ํ™˜๊ฒฝ(์›น ์„œ๋ฒ„) ์—์„œ๋Š” Java/Python ์ฒ˜๋Ÿผ SipHash ๊ฐ™์€ cryptographic ํ•ด์‹œ๋กœ DoS ๋ฐฉ์–ด. C++ ํ‘œ์ค€์€ ๋ช…์‹œ ์•ˆ ํ•จ.


12. unordered_map ์˜ load_factor ์ž„๊ณ„ ์ดˆ๊ณผ โ€” ์–ธ์ œ ์ผ์–ด๋‚˜๋‚˜

ํ•œ ์ค„ ๊ฒฐ๋ก  โ€” load_factor() = size / bucket_count ๊ฐ€ max_load_factor()(๊ธฐ๋ณธ 1.0) ๋ฅผ ๋„˜๋Š” ์ˆœ๊ฐ„ rehash ๋ฐœ์ƒ. ์ฆ‰ ์›์†Œ ์ˆ˜ > ๋ฒ„ํ‚ท ์ˆ˜ ๊ฐ€ ๋˜๋Š” ๋‹ค์Œ insert/emplace ํ˜ธ์ถœ ๋•Œ.

12-1. ์ž„๊ณ„ ์กฐ๊ฑด

1
2
3
4
5
6
7
8
std::unordered_map<int,int> u;
// ๊ธฐ๋ณธ max_load_factor = 1.0
// ์ดˆ๊ธฐ bucket_count ๋Š” ๊ตฌํ˜„ ์ •์˜ (๋ณดํ†ต 1 ๋˜๋Š” 0)

u.insert({1, 100});
// ๋งŒ์•ฝ bucket_count == 1 ์ด๊ณ  size == 1 ์ด๋ฉด load_factor == 1.0
// ๋‹ค์Œ insert ์—์„œ 1.0 ์ดˆ๊ณผ ์˜ˆ์ • โ†’ rehash
u.insert({2, 200});   // โ˜… rehash ๋ฐœ์ƒ (bucket_count 2๋ฐฐ ํ™•์žฅ)

๊ธฐ๋ณธ max_load_factor ๋Š” 1.0 โ€” ํ‰๊ท  ๋ฒ„ํ‚ท 1๊ฐœ๋‹น ์›์†Œ 1๊ฐœ๋ฅผ ์œ ์ง€ํ•˜๋ ค๋Š” ์ •์ฑ…. ๋” ๋นก๋นกํ•˜๊ฒŒ ํ•˜๋ฉด ๋ฉ”๋ชจ๋ฆฌ + ์ถฉ๋Œ โ†‘, ๋” ๋А์Šจํ•˜๊ฒŒ ํ•˜๋ฉด ๋ฉ”๋ชจ๋ฆฌ ์ ˆ์•ฝํ•˜์ง€๋งŒ ์ถฉ๋Œยท์ฒด์ธ ๊ธธ์ด โ†‘.

12-2. rehash ๋™์ž‘ (size > bucket_count ๊ฐ€ ๋œ ์งํ›„ insert)

1
2
3
4
5
1) ์ƒˆ ๋ฒ„ํ‚ท ๋ฐฐ์—ด ํ• ๋‹น (๋ณดํ†ต 2๋ฐฐ ํฌ๊ธฐ, ์†Œ์ˆ˜ ๊ทผ์ฒ˜๋กœ ๋ฐ˜์˜ฌ๋ฆผ)
2) ๋ชจ๋“  ์›์†Œ๋ฅผ hash(key) % new_bucket_count ๋กœ ๋‹ค์‹œ ๋ถ„๋ฐฐ
3) ๊ธฐ์กด ๋ฒ„ํ‚ท ๋ฐฐ์—ด ํ•ด์ œ
๋น„์šฉ: O(n)  โ† 13๋ฒˆ vector ์žฌํ• ๋‹น๊ณผ ๋™์ผ ํŒจํ„ด
๋ถ€์ˆ˜ ํšจ๊ณผ: ๋ชจ๋“  iteratorยทํฌ์ธํ„ฐยท์ฐธ์กฐ ๋ฌดํšจํ™” โ˜…

12-3. ํŠธ๋ฆฌ๊ฑฐ ์‹œ์  ์ •๋ฆฌ

์ƒํ™ฉrehash?
insert ํ›„ size <= bucket_count ร— max_load_factorX
insert ํ›„ size > bucket_count ร— max_load_factorO โ˜…
erase (์›์†Œ ์‚ญ์ œ)์ž๋™ rehash ์—†์Œ
u.rehash(n) ๋ช…์‹œ ํ˜ธ์ถœbucket_count โ‰ฅ n ๋ณด์žฅ์œผ๋กœ ์ฆ‰์‹œ
u.reserve(n) ๋ช…์‹œ ํ˜ธ์ถœsize n ๊นŒ์ง€ rehash ์•ˆ ์ผ์–ด๋‚˜๋„๋ก ์‚ฌ์ „ ํ™•๋ณด
max_load_factor(0.5) ๋กœ ๋‚ฎ์ถค๋‹ค์Œ insert ๋ถ€ํ„ฐ ๋” ์ผ์ฐ ๋ฐœ๋™

12-4. ํšŒํ”ผ ํŒจํ„ด

1
2
3
4
5
6
7
8
9
10
std::unordered_map<int,int> u;
u.reserve(10000);   // ๋ฏธ๋ฆฌ ์ถฉ๋ถ„ํ•œ ๋ฒ„ํ‚ท ํ™•๋ณด โ†’ 10000 ๊นŒ์ง€ rehash 0ํšŒ

for (int i = 0; i < 10000; ++i)
    u.insert({i, i});   // ํ•œ ๋ฒˆ๋„ rehash ์—†์Œ

// โŒ ์•ˆํ‹ฐ ํŒจํ„ด โ€” ๋ฃจํ”„ ๋„์ค‘ iterator ๋ณด๊ด€
auto it = u.insert({1, 100}).first;
for (int i = 0; i < 10000; ++i)
    u.insert({i, i});   // โ˜… ๋„์ค‘์— rehash โ†’ it ๋ฌดํšจ โ†’ UB

ํ•ด์‹œ๋งต์—์„œ iterator ๋ฅผ ๊ธธ๊ฒŒ ๋“ค๊ณ  ๋‹ค๋‹ˆ์ง€ ๋ง ๊ฒƒ โ€” rehash ํ•œ ๋ฒˆ์— ์ „๋ถ€ ๋ฌดํšจ. RB-Tree ๊ธฐ๋ฐ˜ std::map ์€ ์‚ฝ์ž… ์‹œ ๋ฌดํšจํ™” ์—†์Œ (๋…ธ๋“œ ์•ˆ์ •์„ฑ).


13. map ์—์„œ โ€œ๋…ธ๋“œโ€ ๋Š” ๋ญ˜ ๊ฐ€๋ฆฌํ‚ค๋‚˜

ํ•œ ์ค„ ๊ฒฐ๋ก  โ€” std::map ์˜ ๋…ธ๋“œ๋Š” ํž™์— ํ• ๋‹น๋œ RB-Tree ๋…ธ๋“œ 1๊ฐœ ์ด๋ฉฐ, ์•ˆ์— ์ƒ‰๊น” + ๋ถ€๋ชจ/์ขŒ/์šฐ ํฌ์ธํ„ฐ 3๊ฐœ + std::pair<const Key, T> 1๊ฐœ ๊ฐ€ ๋“ค์–ด ์žˆ๋‹ค. iterator ๋Š” ์ด ๋…ธ๋“œ์˜ ์ฃผ์†Œ๋ฅผ ๊ฐ€๋ฆฌํ‚ค๋Š” ํฌ์ธํ„ฐ๋‹ค.

13-1. ๋…ธ๋“œ ๋ฉ”๋ชจ๋ฆฌ ๋ ˆ์ด์•„์›ƒ (libstdc++ ๋‹จ์ˆœํ™”)

1
2
3
4
5
6
7
struct _Rb_tree_node {
    _Rb_tree_color color;            // R or B (1๋ฐ”์ดํŠธ์ง€๋งŒ ์ •๋ ฌ๋กœ 4~8B)
    _Rb_tree_node* parent;           // ๋ถ€๋ชจ 8B
    _Rb_tree_node* left;             // ์™ผ์ชฝ ์ž์‹ 8B
    _Rb_tree_node* right;            // ์˜ค๋ฅธ์ชฝ ์ž์‹ 8B
    std::pair<const Key, T> data;    // ํ‚ค-๊ฐ’ ์Œ โ† ์‚ฌ์šฉ์ž ๋ฐ์ดํ„ฐ
};

std::map<int,int> ๋…ธ๋“œ 1๊ฐœ โ‰ˆ

1
2
3
์ƒ‰(8) + parent(8) + left(8) + right(8) + (ํ‚ค 4 + ๊ฐ’ 4 + pad 4) + heap header(~16)
= 60๋ฐ”์ดํŠธ
โ†’ ๋ฐ์ดํ„ฐ 8B ์œ„ํ•ด 60B โ†’ ํšจ์œจ ~13%

13-2. ๋…ธ๋“œ๋Š” ํž™์— ๋ถ„์‚ฐ ํ• ๋‹น

1
2
3
4
5
6
7
m.insert({1, "a"});   // ๋…ธ๋“œ A ๋ฅผ new ๋กœ ํž™ ํ• ๋‹น
m.insert({2, "b"});   // ๋…ธ๋“œ B ๋ฅผ new ๋กœ ํž™ ํ• ๋‹น (A ์™€ ๋ฉ”๋ชจ๋ฆฌ์ƒ ์ธ์ ‘ ๋ณด์žฅ X)
m.insert({3, "c"});   // ๋…ธ๋“œ C ...

ํž™: โ”Œโ”€โ”€โ”€โ”€โ”€โ”    โ”Œโ”€โ”€โ”€โ”€โ”€โ”    โ”Œโ”€โ”€โ”€โ”€โ”€โ”
    โ”‚ A=1 โ”‚ โ†โ†’ โ”‚ B=2 โ”‚ โ†โ†’ โ”‚ C=3 โ”‚   โ† ํŠธ๋ฆฌ ํฌ์ธํ„ฐ๋กœ ์—ฐ๊ฒฐ, ๋ฉ”๋ชจ๋ฆฌ๋Š” ํฉ์–ด์ง
    โ””โ”€โ”€โ”€โ”€โ”€โ”˜    โ””โ”€โ”€โ”€โ”€โ”€โ”˜    โ””โ”€โ”€โ”€โ”€โ”€โ”˜

์ด ๋ถ„์‚ฐ์ด ๋…ธ๋“œ ์•ˆ์ •์„ฑ ์˜ ์›์ฒœ โ€” ํ•œ ๋…ธ๋“œ ์ด๋™/์‚ญ์ œ๊ฐ€ ๋‹ค๋ฅธ ๋…ธ๋“œ ์ฃผ์†Œ์— ์˜ํ–ฅ ์—†์Œ. ๋™์‹œ์— ์บ์‹œ ์ ๋Œ€์  ์˜ ์›์ธ์ด๊ธฐ๋„ ํ•จ (vector ์™€ ์ •๋ฐ˜๋Œ€).

13-3. iterator ๊ฐ€ ๊ฐ€๋ฆฌํ‚ค๋Š” ๊ฒƒ

1
2
3
4
auto it = m.find(2);
// it ๋Š” ๋…ธ๋“œ B ์˜ ํฌ์ธํ„ฐ (์ •ํ™•ํžˆ๋Š” _Rb_tree_iterator<pair<const int,int>>)
// it->first  == 2     โ† ๋…ธ๋“œ B ์˜ data.first
// it->second == "b"   โ† ๋…ธ๋“œ B ์˜ data.second
  • iterator ์ฆ๊ฐ€ (++it) โ€” RB-Tree ์˜ in-order successor ๋กœ ์ด๋™ โ†’ ์ •๋ ฌ ์ˆœ ๋‹ค์Œ ๋…ธ๋“œ
  • ์‚ญ์ œ๋œ ๋…ธ๋“œ์˜ iterator ๋งŒ ๋ฌดํšจํ™”, ๋‚˜๋จธ์ง€๋Š” ์•ˆ์ „ โ†’ ๋…ธ๋“œ ์•ˆ์ •์„ฑ

13-4. ๋…ธ๋“œ โ†” ๋‹ค๋ฅธ ์ปจํ…Œ์ด๋„ˆ ๋น„๊ต

์ปจํ…Œ์ด๋„ˆ๋…ธ๋“œ๋ž€?๋ฉ”๋ชจ๋ฆฌ ์œ„์น˜iterator ์•ˆ์ •์„ฑ
std::vector<T>๋…ธ๋“œ ๊ฐœ๋… ์—†์Œ์—ฐ์† ๋ฐฐ์—ด์žฌํ• ๋‹น ์‹œ ๋ชจ๋‘ ๋ฌดํšจ
std::list<T>prev + next + Tํž™ ๋ถ„์‚ฐ๋งค์šฐ ์•ˆ์ •
std::map<K,V>color + parent/left/right + pairํž™ ๋ถ„์‚ฐ์‚ฝ์ž… ๋ฌดํšจ X, ์‚ญ์ œ๋Š” ๋ณธ์ธ๋งŒ
std::unordered_map<K,V>next + pair (์ฒด์ด๋‹ ๋…ธ๋“œ)ํž™ ๋ถ„์‚ฐ + ๋ฒ„ํ‚ท ๋ฐฐ์—ดrehash ์‹œ ๋ชจ๋‘ ๋ฌดํšจ

โ€œmap ์—์„œ ๋…ธ๋“œ๋Š” ํŠธ๋ฆฌ ๋…ธ๋“œ, vector ์—์„œ ์›์†Œ๋Š” ๋ฐฐ์—ด ์นธโ€ โ€” ๋…ธ๋“œ ๋‹จ์œ„ ์ž๋ฃŒ๊ตฌ์กฐ๋Š” ํ•ญ์ƒ ํž™์— ํฉ๋ฟŒ๋ ค์ ธ ์บ์‹œ ์นœํ™”์„ฑ์„ ์žƒ๋Š” ๋Œ€๊ฐ€๋กœ iterator ์•ˆ์ •์„ฑ๊ณผ ๊ฐœ๋ณ„ ์‚ฝ์ž…/์‚ญ์ œ O(log n) ์„ ์–ป๋Š”๋‹ค.


14. ํž™ = ๋ฉ”๋ชจ๋ฆฌ ํ• ๋‹น ์‹œ์  ์ด์•ผ๊ธฐ์ธ๊ฐ€?

๋ถ€๋ถ„ ์ •๋‹ต โ€” ํž™์€ โ€œ๋™์  ํ• ๋‹น์ด ์ผ์–ด๋‚˜๋Š” ๋ฉ”๋ชจ๋ฆฌ ์˜์—ญโ€ ์ด์ง€ ์‹œ์  ์ž์ฒด๋Š” ์•„๋‹ˆ๋‹ค. โ€œํ• ๋‹น ์‹œ์ ์ด ๋Ÿฐํƒ€์ž„โ€ ์ด๋ผ๋Š” ๊ฒŒ ํž™์˜ ํŠน์ง•์ด๊ณ , ๊ทธ ๊ฒฐ๊ณผ๊ฐ€ โ€œ์ˆ˜๋ช…์„ ํ”„๋กœ๊ทธ๋ž˜๋จธ๊ฐ€ ์ œ์–ดํ•œ๋‹คโ€ ๋Š” ์‹œ์  ์ž์œ ๋„๋‹ค.

14-1. ๋‘ ์‹œ์  + ๋‘ ์˜์—ญ

1
2
3
4
5
๊ตฌ๋ถ„          | ์˜์—ญ      | ํ• ๋‹น ์‹œ์           | ํ•ด์ œ ์‹œ์ 
โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€|โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€|โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€|โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€
์ •์ /์ „์—ญ    | data/bss | ์ปดํŒŒ์ผ/ํ”„๋กœ๊ทธ๋žจ ์‹œ์ž‘ | ํ”„๋กœ๊ทธ๋žจ ์ข…๋ฃŒ
์ง€์—ญ ๋ณ€์ˆ˜    | ์Šคํƒ      | ํ•จ์ˆ˜ ์ง„์ž… (๋Ÿฐํƒ€์ž„)   | ํ•จ์ˆ˜ ์ข…๋ฃŒ (์ž๋™, RAII)
new / malloc | ํž™       | ๋Ÿฐํƒ€์ž„ (์š”์ฒญ ์ฆ‰์‹œ)   | delete/free ํ˜ธ์ถœ ์‹œ โ˜…
ย ์Šคํƒํž™
์‹œ์ ํ•จ์ˆ˜ ์ง„์ž… ์‹œ ์ž๋™๋Ÿฐํƒ€์ž„ new ํ˜ธ์ถœ ์‹œ
ํ•ด์ œํ•จ์ˆ˜ ์ข…๋ฃŒ ์‹œ ์ž๋™delete ๋ช…์‹œ ํ˜ธ์ถœ (๋˜๋Š” ์Šค๋งˆํŠธ ํฌ์ธํ„ฐ)
์†๋„๋งค์šฐ ๋น ๋ฆ„ (SP ์ด๋™)๋А๋ฆผ (ํ• ๋‹น์ž ์•Œ๊ณ ๋ฆฌ์ฆ˜)
ํฌ๊ธฐ์ž‘์Œ (~MB)ํผ (~GB)
๋‹จํŽธํ™”์—†์Œ์žˆ์Œ
์ˆ˜๋ช…์Šค์ฝ”ํ”„ ํ•œ์ •ํ”„๋กœ๊ทธ๋ž˜๋จธ ์ œ์–ด

14-2. ๊ทธ๋ž˜์„œ ํž™ = ์‹œ์ ์ธ๊ฐ€, ์˜์—ญ์ธ๊ฐ€?

์—„๋ฐ€ํ•˜๊ฒŒ๋Š” ์˜์—ญ. ๋‹ค๋งŒ โ€œ์™œ ํž™์„ ์“ฐ๋Š”๊ฐ€?โ€ ์˜ ๋‹ต์ด ๊ณง ์‹œ์  ์ด์•ผ๊ธฐ๋‹ค:

  • ๊ฐ์ฒด์˜ ์ˆ˜๋ช…์„ ํ•จ์ˆ˜ ์Šค์ฝ”ํ”„ ๋ฐ–์œผ๋กœ ์—ฐ์žฅํ•ด์•ผ ํ•œ๋‹ค
  • ๊ฐ์ฒด ํฌ๊ธฐ๊ฐ€ ์ปดํŒŒ์ผ ํƒ€์ž„์— ์ •ํ•ด์ง€์ง€ ์•Š๋Š”๋‹ค (๋Ÿฐํƒ€์ž„ ์ž…๋ ฅ์— ๋”ฐ๋ผ)
  • ๊ฐ์ฒด๊ฐ€ ๋„ˆ๋ฌด ์ปค์„œ ์Šคํƒ ํ•œ๊ณ„๋ฅผ ๋„˜๋Š”๋‹ค

์ด ์„ธ ๊ฐ€์ง€๊ฐ€ ์ถฉ์กฑ๋˜๋ฉด ํž™. ๊ทธ๋ž˜์„œ ํž™์„ โ€œ๋Ÿฐํƒ€์ž„ ๋™์  ํ• ๋‹น์˜ ์˜์—ญโ€ ์ด๋ผ๊ณ  ์ค„์—ฌ ๋ถ€๋ฅด๊ณ , ํšŒํ™”์—์„œ๋Š” โ€œํ• ๋‹น ์‹œ์ โ€ ์œผ๋กœ ํ†ตํ•˜๊ธฐ๋„ ํ•œ๋‹ค.

14-3. STL ์ปจํ…Œ์ด๋„ˆ์˜ ํž™ ์‚ฌ์šฉ

์ปจํ…Œ์ด๋„ˆํž™ ์‚ฌ์šฉ ํŒจํ„ด
std::vector<T>๋ฐ์ดํ„ฐ ๋ฐฐ์—ด 1๊ฐœ๋ฅผ ํž™์— ํ• ๋‹น, ์žฌํ• ๋‹น ์‹œ ์ƒˆ ๋ฐฐ์—ด + ๋ณต์‚ฌ
std::list<T>๋…ธ๋“œ 1๊ฐœ์”ฉ ๋”ฐ๋กœ ํž™ ํ• ๋‹น (๋ถ„์‚ฐ)
std::map<K,V>๋…ธ๋“œ 1๊ฐœ์”ฉ ๋”ฐ๋กœ ํž™ ํ• ๋‹น (๋ถ„์‚ฐ)
std::unordered_map<K,V>๋ฒ„ํ‚ท ๋ฐฐ์—ด 1๊ฐœ + ๋…ธ๋“œ๋“ค (์ฒด์ด๋‹) ๋ชจ๋‘ ํž™

๊ฒŒ์ž„ ์—”์ง„์ด TArray ๋ฅผ 1๊ธ‰ ์‹œ๋ฏผ์œผ๋กœ ๋‘๋Š” ๊ฑด, ํž™ ํ• ๋‹น ํšŸ์ˆ˜ ์ž์ฒด๋ฅผ ์ค„์ด๋Š” ๊ฒƒ ๋„ ๋ชฉ์ ์ด๋‹ค. ๋…ธ๋“œ 1๋งŒ ๊ฐœ๋ฅผ ํž™์— 1๋งŒ ๋ฒˆ new ํ•˜๋Š” ๊ฒƒ๋ณด๋‹ค ๋ฐฐ์—ด 1๊ฐœ๋กœ ํฐ ๋ธ”๋ก ํ•œ ๋ฒˆ ํ• ๋‹น์ด ํ›จ์”ฌ ๋น ๋ฅด๊ณ  ์บ์‹œ ์นœํ™”์ .

14๋ฒˆ ยง3-6 ๋…ธ๋“œ ๋ฉ”๋ชจ๋ฆฌ ๋ ˆ์ด์•„์›ƒ + 11๋ฒˆ ์Šค๋งˆํŠธ ํฌ์ธํ„ฐ(ํž™ ์ˆ˜๋ช… ์ž๋™ํ™”) ์™€ ๋ฌถ์–ด ํ•จ๊ป˜ ๋‹ตํ•˜๋ฉด ๊นŠ์ด๊ฐ€ ์‚ฐ๋‹ค.


15. ํ•ด์‹œ = ๋ฉ”๋ชจ๋ฆฌ ํ• ๋‹น ์‹œ ํ•„์š”ํ•œ ์ •์ˆ˜๊ฐ’?

ํ•œ ์ค„ ๊ฒฐ๋ก  โ€” ์•„๋‹™๋‹ˆ๋‹ค. ํ•ด์‹œ๋Š” ํ• ๋‹น๊ณผ ๋ฌด๊ด€ํ•˜๋‹ค. ํ•ด์‹œ๋Š” ์ด๋ฏธ ํ• ๋‹น๋œ ๋ฒ„ํ‚ท ๋ฐฐ์—ด์—์„œ โ€œ์–ด๋А ์Šฌ๋กฏ์„ ์“ธ์ง€ ์ธ๋ฑ์‹ฑโ€ ํ•˜๋Š” ์ •์ˆ˜๊ฐ’์ด๋‹ค. ๋ฉ”๋ชจ๋ฆฌ๋Š” new/malloc ์ด ์žก๊ณ , ํ•ด์‹œ๋Š” ๊ทธ ์•ˆ์—์„œ ์œ„์น˜๋งŒ ๊ฒฐ์ •ํ•œ๋‹ค.

15-1. ๋‘ ๊ฐ€์ง€๋ฅผ ๋ถ„๋ฆฌ

๋‹จ๊ณ„๋ˆ„๊ฐ€ ํ•˜๋Š”๊ฐ€๊ฒฐ๊ณผ
๋ฉ”๋ชจ๋ฆฌ ํ• ๋‹นnew / malloc (ํž™ ํ• ๋‹น์ž)๋ฒ„ํ‚ท ๋ฐฐ์—ด์˜ ๋ฉ”๋ชจ๋ฆฌ ์ฃผ์†Œ ํ™•๋ณด
์œ„์น˜ ๊ฒฐ์ •ํ•ด์‹œ ํ•จ์ˆ˜โ€œ์ด ํ‚ค๋Š” buckets[11] ์— ๋„ฃ์žโ€
1
2
3
4
5
6
std::unordered_map<std::string, int> u;
u.reserve(16);   // โ‘  ํ• ๋‹น โ€” ํž™์— 16์นธ์งœ๋ฆฌ ๋ฒ„ํ‚ท ๋ฐฐ์—ด ๋งˆ๋ จ (ํ•ด์‹œ ๋ฌด๊ด€)

u["Alice"] = 30; // โ‘ก ์œ„์น˜ ๊ฒฐ์ • โ€” hash("Alice") % 16 = 11 โ†’ buckets[11] ์— ์ €์žฅ
                 //                ^^^^^^^^^^^^^^^^^^
                 //                ์—ฌ๊ธฐ๊ฐ€ ํ•ด์‹œ. ํ• ๋‹น์ด ์•„๋‹ˆ๋ผ ์ธ๋ฑ์‹ฑ.

15-2. ํ•ด์‹œ์˜ ์ •ํ™•ํ•œ ์ •์˜

ํ•ด์‹œ = ํ‚ค๋ฅผ ์ •์ˆ˜ ๊ณต๊ฐ„์— ๋งคํ•‘ํ•˜๋Š” ํ•จ์ˆ˜์˜ ๊ฒฐ๊ณผ๊ฐ’. ๊ทธ ์ •์ˆ˜๋ฅผ ๋ชจ๋“ˆ๋กœ ์—ฐ์‚ฐํ•ด ๋ฒ„ํ‚ท ์ธ๋ฑ์Šค๋กœ ์“ด๋‹ค.

1
2
3
4
"Alice" โ”€โ”€hash()โ”€โ”€โ–ถ 4283950122 โ”€โ”€% bucket_countโ”€โ”€โ–ถ 11
                    โ†‘                              โ†‘
                 ํ•ด์‹œ๊ฐ’                        ๋ฒ„ํ‚ท ์ธ๋ฑ์Šค
                 (ํ• ๋‹น ์•„๋‹˜)                  (๋ฐฐ์—ด ์ฒจ์ž)

15-3. ๋น„์œ  โ€” ๋„์„œ๊ด€ ์ฑ…์žฅ

1
2
๋ฉ”๋ชจ๋ฆฌ ํ• ๋‹น = "16์นธ์งœ๋ฆฌ ์ฑ…์žฅ์„ ์‚ฌ์„œ ๋„์„œ๊ด€์— ๋†“๋Š”๋‹ค"   โ† ํ•œ ๋ฒˆ
ํ•ด์‹œ      = "์ด ์ฑ…์˜ ISBN ๋์ž๋ฆฌ ๋ณด๊ณ  11๋ฒˆ ์นธ์— ๊ฝ‚์ž"  โ† ์ฑ…๋งˆ๋‹ค

์ฑ…์žฅ(๋ฒ„ํ‚ท ๋ฐฐ์—ด) ์€ ์ด๋ฏธ ์žˆ๊ณ , ํ•ด์‹œ๋Š” ์ƒˆ ์ฑ…์„ ์–ด๋А ์นธ์— ๊ฝ‚์„์ง€ / ์ฐพ์„ ์ฑ…์ด ์–ด๋А ์นธ์— ์žˆ๋Š”์ง€ ์•Œ๋ ค์ค„ ๋ฟ. ์ฑ…์žฅ์„ ์‚ฌ๊ฑฐ๋‚˜ ๋Š˜๋ฆฌ๋Š”(rehash) ์ผ์€ ํ•ด์‹œ๊ฐ€ ์•„๋‹ˆ๋ผ ํ• ๋‹น์ž๊ฐ€ ํ•œ๋‹ค.

15-4. ์‹œ์  ์ •๋ฆฌ

์‹œ์ ์ผ์–ด๋‚˜๋Š” ์ผํ•ด์‹œ ์‚ฌ์šฉ?
unordered_map ์ƒ์„ฑ์ดˆ๊ธฐ ๋ฒ„ํ‚ท ๋ฐฐ์—ด ํ• ๋‹นX (ํ• ๋‹น์ž๋งŒ)
insert(k, v)hash(k) % N โ†’ ๋ฒ„ํ‚ท ๊ฒฐ์ • โ†’ ๋…ธ๋“œ ์‚ฝ์ž…O
find(k)hash(k) % N โ†’ ๋ฒ„ํ‚ท ๊ฒฐ์ • โ†’ ๋น„๊ตO
load_factor ์ดˆ๊ณผ์ƒˆ ๋ฒ„ํ‚ท ๋ฐฐ์—ด ํ• ๋‹น + ๋ชจ๋“  ์›์†Œ ์žฌ๋ฐฐ์น˜O (์žฌ๋ฐฐ์น˜ ์‹œ ๋ชจ๋“  ํ‚ค hash ์žฌ๊ณ„์‚ฐ)
erase(k)hash(k) % N โ†’ ๋ฒ„ํ‚ท ๊ฒฐ์ • โ†’ ๋…ธ๋“œ ์ œ๊ฑฐO

ํ•ด์‹œ๋Š” insert/find/erase ๊ฐ€ ์ผ์–ด๋‚  ๋•Œ๋งˆ๋‹ค ํ‚ค๋งˆ๋‹ค 1ํšŒ์”ฉ ํ˜ธ์ถœ๋œ๋‹ค. ๋ฉ”๋ชจ๋ฆฌ ํ• ๋‹น์€ ์ปจํ…Œ์ด๋„ˆ ์ƒ์„ฑยทrehash ๊ฐ™์€ ๋“œ๋ฌธ ์‚ฌ๊ฑด์—์„œ๋งŒ ์ผ์–ด๋‚จ. ๋‘ ์‚ฌ๊ฑด์˜ ๋นˆ๋„๋ถ€ํ„ฐ ๋‹ค๋ฅด๋‹ค.

15-5. ๊ทธ๋Ÿผ โ€œํ• ๋‹น ์‹œ ํ•„์š”ํ•œ ์ •์ˆ˜โ€ ๋Š” ๋ญ๊ฐ€ ์žˆ๋‚˜?

์งˆ๋ฌธ์˜ ์ง๊ด€๊ณผ ๊ฐ€์žฅ ๊ฐ€๊นŒ์šด ๊ฑด ํฌ์ธํ„ฐ ๊ฐ’ (= ๋ฉ”๋ชจ๋ฆฌ ์ฃผ์†Œ). new T ๋Š” ํž™์—์„œ ๋นˆ ์˜์—ญ์„ ์ฐพ์•„ ๊ทธ ์˜์—ญ์˜ ์‹œ์ž‘ ์ฃผ์†Œ(์ •์ˆ˜) ๋ฅผ ๋ฐ˜ํ™˜ํ•œ๋‹ค.

1
2
int* p = new int(42);
// p ์˜ ๊ฐ’ = 0x7ffd1c00abc0  โ† ์ด๊ฒŒ "ํ• ๋‹น ์‹œ ๋ฐ›๋Š” ์ •์ˆ˜"

ํ•ด์‹œ๊ฐ’๊ณผ ํฌ์ธํ„ฐ๊ฐ’์€ ๋‘˜ ๋‹ค ์ •์ˆ˜์ง€๋งŒ ์˜๋ฏธ๊ฐ€ ๋‹ค๋ฅด๋‹ค:

ย ํ•ด์‹œ๊ฐ’ํฌ์ธํ„ฐ๊ฐ’
์ถœ์ฒ˜ํ•ด์‹œ ํ•จ์ˆ˜๊ฐ€ ํ‚ค๋กœ๋ถ€ํ„ฐ ๊ณ„์‚ฐํ• ๋‹น์ž๊ฐ€ ๋นˆ ๋ฉ”๋ชจ๋ฆฌ ์˜์—ญ์„ ์ฐพ์•„ ๋ฐ˜ํ™˜
์šฉ๋„๋ฒ„ํ‚ท ๋ฐฐ์—ด์˜ ์ธ๋ฑ์Šค๋ฉ”๋ชจ๋ฆฌ์˜ ์ฃผ์†Œ
๊ฒฐ์ •์„ฑ๊ฐ™์€ ํ‚ค โ†’ ๊ฐ™์€ ํ•ด์‹œ (ํ™•์ •)๊ฐ™์€ ํ˜ธ์ถœ๋„ ๋งค๋ฒˆ ๋‹ค๋ฅธ ์ฃผ์†Œ (๋น„ํ™•์ •)
๋ฒ”์œ„[0, bucket_count) ๋กœ ๋ชจ๋“ˆ๋กœ๊ฐ€์ƒ ์ฃผ์†Œ ๊ณต๊ฐ„ ์ „์ฒด

15-6. ์ •์ •๋œ ํ•œ ์ค„ ์ •์˜

ํ•ด์‹œ๋Š” โ€œํ‚ค โ†’ ๋ฒ„ํ‚ท ์ธ๋ฑ์Šคโ€ ๋ณ€ํ™˜์— ์“ฐ๋Š” ์ •์ˆ˜๊ฐ’์ด์ง€, ๋ฉ”๋ชจ๋ฆฌ ํ• ๋‹น๊ณผ๋Š” ๋ฌด๊ด€. ํ• ๋‹น์€ ํ• ๋‹น์ž(new/malloc) ์˜ ์ผ์ด๊ณ , ํ•ด์‹œ๋Š” ์ด๋ฏธ ํ• ๋‹น๋œ ๋ฒ„ํ‚ท ๋ฐฐ์—ด ์•ˆ์—์„œ ์œ„์น˜๋งŒ ๊ฒฐ์ •ํ•œ๋‹ค.

ยง11 (ํ•ด์‹œยท๋ฒ„ํ‚ท) + ยง14 (ํž™ = ์˜์—ญ) ๋ฅผ ๋ฌถ์–ด์„œ ๋ณด๋ฉด, โ€œํ• ๋‹น์ž๊ฐ€ ๋ฉ”๋ชจ๋ฆฌ๋ฅผ ์žก๊ณ  โ†’ ๊ทธ ์•ˆ์—์„œ ํ•ด์‹œ๋กœ ์Šฌ๋กฏ์„ ๊ณ ๋ฅธ๋‹คโ€ ๋Š” ๋‘ ๋‹จ๊ณ„๊ฐ€ ๊น”๋”ํ•˜๊ฒŒ ๋ถ„๋ฆฌ๋œ๋‹ค.


16. ํ•ด์‹œ๋Š” ํฌ์ธํ„ฐ ์ฃผ์†Œ๊ฐ’ ๊ฐ™์€ ๊ฑด๊ฐ€?

ํ•œ ์ค„ ๊ฒฐ๋ก  โ€” ์•„๋‹™๋‹ˆ๋‹ค. ๋‘˜ ๋‹ค ์ •์ˆ˜์ง€๋งŒ ์ถœ์ฒ˜ยท์šฉ๋„ยท๊ฒฐ์ •์„ฑ์ด ์ •๋ฐ˜๋Œ€๋‹ค. ํฌ์ธํ„ฐ๋Š” ํ• ๋‹น์ž๊ฐ€ ์žก์•„ ์ค€ ๋ฉ”๋ชจ๋ฆฌ ์ฃผ์†Œ (๊ทธ๊ณณ์— ๊ฐ€๋ฉด ๋ฐ์ดํ„ฐ๊ฐ€ ์žˆ๋‹ค), ํ•ด์‹œ๋Š” ํ‚ค๋กœ๋ถ€ํ„ฐ ๊ณ„์‚ฐํ•œ ์ธ๋ฑ์Šค ์žฌ๋ฃŒ (๋ฐฐ์—ด์˜ ๋ช‡ ๋ฒˆ ์นธ์„ ์“ธ์ง€). ํ—ท๊ฐˆ๋ฆฌ๋ฉด ๋ฉด์ ‘์—์„œ ๊นจ์ง„๋‹ค.

16-1. ๊ฒฐ์ •์  ์ฐจ์ด โ€” โ€œ์–ด๋””์„œ ์˜ค๋Š”๊ฐ€โ€

1
2
3
4
5
6
7
8
9
10
11
ํฌ์ธํ„ฐ ์ฃผ์†Œ๊ฐ’:
   int* p = new int(42);
   // ํ• ๋‹น์ž(OS/ํ• ๋‹น์ž ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ)๊ฐ€ ๋นˆ ๋ฉ”๋ชจ๋ฆฌ ์˜์—ญ์„ ์ฐพ์•„ ๊ทธ ์ฃผ์†Œ๋ฅผ ๋ฐ˜ํ™˜
   // โ†’ p == 0x7ffd1c00abc0 ๊ฐ™์€ ๊ฐ€์ƒ ์ฃผ์†Œ
   // โ†’ ๊ฐ™์€ ์ฝ”๋“œ ๋‘ ๋ฒˆ ์‹คํ–‰ํ•˜๋ฉด ๋งค๋ฒˆ ๋‹ค๋ฅธ ๊ฐ’ (ASLR + ํž™ ์ƒํƒœ์— ๋”ฐ๋ผ)

ํ•ด์‹œ๊ฐ’:
   size_t h = std::hash<std::string>{}("Alice");
   // ํ•ด์‹œ ํ•จ์ˆ˜๊ฐ€ ํ‚ค ์ž์ฒด๋กœ๋ถ€ํ„ฐ ๊ณ„์‚ฐ
   // โ†’ h == 4283950122 (์˜ˆ์‹œ)
   // โ†’ ๊ฐ™์€ ํ‚ค "Alice" ๋Š” ๊ฐ™์€ ํ”„๋กœ์„ธ์Šค์—์„œ ํ•ญ์ƒ ๊ฐ™์€ ๊ฐ’ โ˜…

16-2. ๋น„๊ตํ‘œ (์ด๋ฒˆ ์งˆ๋ฌธ ํ•ต์‹ฌ)

์†์„ฑํฌ์ธํ„ฐ ์ฃผ์†Œ๊ฐ’ํ•ด์‹œ๊ฐ’
๋ˆ„๊ฐ€ ๋งŒ๋“œ๋‚˜ํ• ๋‹น์ž (new/malloc)ํ•ด์‹œ ํ•จ์ˆ˜ (std::hash<K>)
๋ฌด์—‡์œผ๋กœ๋ถ€ํ„ฐ๋น„์–ด์žˆ๋Š” ๋ฉ”๋ชจ๋ฆฌ ์˜์—ญ์„ ์ฐพ์•„ํ‚ค์˜ ๋‚ด์šฉ์œผ๋กœ๋ถ€ํ„ฐ ๊ณ„์‚ฐ
์˜๋ฏธโ€œ์—ฌ๊ธฐ ๊ฐ€๋ฉด ๋ฐ์ดํ„ฐ๊ฐ€ ์žˆ๋‹คโ€ (์ฐธ์กฐ)โ€œ์ด ํ‚ค๋Š” N๋ฒˆ ์นธ์— ๋„ฃ์–ด๋ผโ€ (์ธ๋ฑ์Šค ์žฌ๋ฃŒ)
๊ฒฐ์ •์„ฑ๊ฐ™์€ ํ˜ธ์ถœ๋„ ๋งค๋ฒˆ ๋‹ค๋ฆ„ (๋น„๊ฒฐ์ •์ )๊ฐ™์€ ํ‚ค โ†’ ํ•ญ์ƒ ๊ฐ™์€ ๊ฐ’ (๊ฒฐ์ •์ ) โ˜…
์—ญ์ฐธ์กฐ ๊ฐ€๋Šฅ?*p ๋กœ ๋ฐ์ดํ„ฐ ์ ‘๊ทผ ๊ฐ€๋Šฅ์—ญ์ฐธ์กฐ ๋ถˆ๊ฐ€ โ€” ๊ทธ๋ƒฅ ์ •์ˆ˜
์œ ํšจ์„ฑํ• ๋‹น๋œ ๋ฉ”๋ชจ๋ฆฌ ํ•œ์ •. delete ํ›„ ๋Œ•๊ธ€๋งํ•ญ์ƒ ์œ ํšจ (์ˆœ์ˆ˜ ํ•จ์ˆ˜ ๊ฒฐ๊ณผ)
์ถฉ๋Œ ๊ฐ€๋Šฅ?๋‘ ๊ฐ์ฒด๊ฐ€ ๊ฐ™์€ ์ฃผ์†Œ? โ€” ๋ถˆ๊ฐ€๋Šฅ๋‘ ํ‚ค๊ฐ€ ๊ฐ™์€ ํ•ด์‹œ? โ€” ๊ฐ€๋Šฅ (์ถฉ๋Œ)
๋ฒ”์œ„๊ฐ€์ƒ ์ฃผ์†Œ ๊ณต๊ฐ„ ์ „์ฒด (~64๋น„ํŠธ ํ’€ ๋ฒ”์œ„)size_t ์ •์ˆ˜ (๋ชจ๋“ˆ๋กœ ํ›„ [0, bucket_count))

16-3. ๊ฐ€์žฅ ๊ฒฐ์ •์ ์ธ ํ•œ ๊ฐ€์ง€ โ€” ๊ฒฐ์ •์„ฑ

1
2
3
4
5
6
7
8
9
10
11
12
// ํฌ์ธํ„ฐ: ๋งค๋ฒˆ ๋‹ค๋ฆ„
int* a = new int(1);   // 0x7ffd1c00abc0
int* b = new int(1);   // 0x7ffd1c00abe0  โ† ๊ฐ™์€ ๊ฐ’ 1 ์ธ๋ฐ ์ฃผ์†Œ ๋‹ค๋ฆ„

// ํ•ด์‹œ: ํ•ญ์ƒ ๊ฐ™์Œ
size_t h1 = std::hash<int>{}(1);   // ์˜ˆ: 1
size_t h2 = std::hash<int>{}(1);   // ์˜ˆ: 1  โ† ๊ฐ™์€ ํ‚ค๋Š” ํ•ญ์ƒ ๊ฐ™์€ ํ•ด์‹œ

// ๋‹ค๋ฅธ ํ‚ค๊ฐ€ ๊ฐ™์€ ํ•ด์‹œ์ผ ์ˆ˜๋Š” ์žˆ์Œ (์ถฉ๋Œ)
size_t h3 = std::hash<std::string>{}("foo");
size_t h4 = std::hash<std::string>{}("xyz");
// h3 == h4 ๊ฐ€๋Šฅ โ†’ ๊ฐ™์€ ๋ฒ„ํ‚ท์— ๋“ค์–ด๊ฐ โ†’ ์ถฉ๋Œ

์ด ๊ฒฐ์ •์„ฑ์ด ํ•ด์‹œํ…Œ์ด๋ธ”์˜ ๋ณธ์งˆ. ๋งŒ์•ฝ hash("Alice") ๊ฐ€ ํ˜ธ์ถœ๋งˆ๋‹ค ๋‹ค๋ฅธ ๊ฐ’์ด๋ฉด ํ•œ ๋ฒˆ ๋„ฃ์€ ๋’ค ๋‹ค์‹œ ์ฐพ์„ ์ˆ˜ ์—†๋‹ค.

16-4. โ€œ๊ทธ๋ž˜๋„ ๋‘˜ ๋‹ค ์ •์ˆ˜ ์•„๋‹ˆ๋ƒโ€

๋งž๋‹ค. ๊ทธ๋ž˜์„œ ๊ณตํ†ต์ ์ด ์žˆ๊ธด ํ•˜๋‹ค:

  • ๋‘˜ ๋‹ค ๋ณดํ†ต 64๋น„ํŠธ ์ •์ˆ˜ (size_t, uintptr_t)
  • ๋‘˜ ๋‹ค ์–ด๋–ค ์œ„์น˜๋ฅผ ์‹๋ณ„ํ•˜๋Š” ๋ฐ ์“ฐ์ž„ (ํฌ์ธํ„ฐ = ๋ฉ”๋ชจ๋ฆฌ ์œ„์น˜, ํ•ด์‹œ = ๋ฒ„ํ‚ท ์œ„์น˜)
  • ๋‘˜ ๋‹ค โ€œraw value ๋งŒ ๋ณด๋ฉด ์˜๋ฏธ ์—†๋Š” ์ˆซ์žโ€

ํ•˜์ง€๋งŒ ์œ„์น˜์˜ ์ •์˜๊ฐ€ ๋‹ค๋ฅด๋‹ค:

1
2
ํฌ์ธํ„ฐ:  RAM ์˜ ์ ˆ๋Œ€ ์ฃผ์†Œ โ€” OS ๊ฐ€ ๊ฐ€์ƒ ๋ฉ”๋ชจ๋ฆฌ ๋งคํ•‘์„ ํ•ด ์ค˜์•ผ ์ง„์งœ ๋ฐ์ดํ„ฐ์— ๋‹ฟ์Œ
ํ•ด์‹œ:    ๋ฒ„ํ‚ท ๋ฐฐ์—ด์˜ ์ƒ๋Œ€ ์ธ๋ฑ์Šค โ€” ๋ชจ๋“ˆ๋กœ ์—ฐ์‚ฐ์„ ํ•œ ๋’ค์—์•ผ ์˜๋ฏธ๊ฐ€ ์ƒ๊น€

16-5. ํ—ท๊ฐˆ๋ฆฌ์ง€ ์•Š๋Š” ๋น„์œ 

1
2
3
4
5
6
7
8
ํฌ์ธํ„ฐ = ์ง‘ ์ฃผ์†Œ
   "์„œ์šธ์‹œ ๊ฐ•๋‚จ๊ตฌ ํ…Œํ—ค๋ž€๋กœ 123๋ฒˆ์ง€" โ€” ๊ทธ ์œ„์น˜์— ๊ฐ€๋ฉด ์ง„์งœ ์ง‘(๋ฐ์ดํ„ฐ) ์ด ์žˆ๋‹ค.
   ์ฃผ์†Œ ์ž์ฒด๋กœ ๋ฐ์ดํ„ฐ๋ฅผ ์ฐพ์•„๊ฐˆ ์ˆ˜ ์žˆ๋‹ค.

ํ•ด์‹œ = ์‚ฌ๋ฌผํ•จ ๋ฒˆํ˜ธ ๋ฝ‘๊ธฐ
   ์‚ฌ๋ฌผํ•จ 1000๊ฐœ์งœ๋ฆฌ ๋ณด๊ด€์†Œ์—์„œ "์ด๋ฆ„์˜ ์ž์Œ ํ•ฉ % 1000" ์œผ๋กœ ๋ฒˆํ˜ธ ๊ฒฐ์ •.
   ๊ฐ™์€ ์ด๋ฆ„์€ ํ•ญ์ƒ ๊ฐ™์€ ๋ฒˆํ˜ธ. ๋‹ค๋ฅธ ์ด๋ฆ„์ด ๊ฐ™์€ ๋ฒˆํ˜ธ์ผ ์ˆ˜๋„ ์žˆ์Œ (์ถฉ๋Œ).
   ๋ฒˆํ˜ธ๋งŒ ์•Œ์•„๋„ ์‚ฌ๋ฌผํ•จ์ด ์–ด๋”” ์žˆ๋Š”์ง€(๋ฉ”๋ชจ๋ฆฌ ์ฃผ์†Œ) ๋Š” ๋ชจ๋ฆ„.

16-6. ๊ทธ๋Ÿผ ๋‘˜์ด ๋งŒ๋‚˜๋Š” ์ง€์ ์€?

ํ•ด์‹œํ…Œ์ด๋ธ” ๋‚ด๋ถ€์—์„œ ํ•ด์‹œ โ†’ ์ธ๋ฑ์Šค โ†’ ์Šฌ๋กฏ ์ฃผ์†Œ ํ๋ฆ„์€ ๊ฒฐ๊ตญ ํฌ์ธํ„ฐ๋กœ ๋๋‚œ๋‹ค:

1
2
3
4
5
6
7
8
9
10
11
12
13
ํ‚ค "Alice"
   โ”‚
   โ–ผ hash()
4283950122          โ† ํ•ด์‹œ๊ฐ’ (์ •์ˆ˜, ๊ฒฐ์ •์ )
   โ”‚
   โ–ผ % 16
11                  โ† ๋ฒ„ํ‚ท ์ธ๋ฑ์Šค
   โ”‚
   โ–ผ &buckets[11]
0x7ffd1c00abc8      โ† ์Šฌ๋กฏ์˜ ์ฃผ์†Œ (ํฌ์ธํ„ฐ)
   โ”‚
   โ–ผ *
{"Alice", 30}       โ† ์‹ค์ œ ๋ฐ์ดํ„ฐ

ํ•ด์‹œ๋Š” ์ธ๋ฑ์Šค ์žฌ๋ฃŒ ๊นŒ์ง€๋งŒ, ๊ฑฐ๊ธฐ์„œ๋ถ€ํ„ฐ ๋ฉ”๋ชจ๋ฆฌ ์ฃผ์†Œ(ํฌ์ธํ„ฐ) ๋กœ ๋ณ€ํ™˜๋˜๋Š” ๊ฒƒ์€ ๋ฐฐ์—ด ์ฒจ์ž ์—ฐ์‚ฐ(buckets + 11 * sizeof(slot)) ์˜ ์ผ์ด๋‹ค.

16-7. ์ •์ •๋œ ํ•œ ์ค„ ์ •์˜

ํ•ด์‹œ๋Š” โ€œ๊ฐ™์€ ์ž…๋ ฅ โ†’ ๊ฐ™์€ ์ถœ๋ ฅโ€ ์ •์ˆ˜๊ณ , ํฌ์ธํ„ฐ๋Š” โ€œํ• ๋‹น์ž๊ฐ€ ์žก์•„ ์ค€ ๋ฉ”๋ชจ๋ฆฌ ์ฃผ์†Œโ€ ๋‹ค. ๋‘˜ ๋‹ค ์ •์ˆ˜๋ผ๋Š” ์ ๋งŒ ๊ฐ™๊ณ  ์ถœ์ฒ˜ยท๊ฒฐ์ •์„ฑยท์—ญ์ฐธ์กฐ ๊ฐ€๋Šฅ์„ฑ์ด ๋ชจ๋‘ ๋‹ค๋ฅด๋‹ค. ํฌ์ธํ„ฐ๋Š” ๊ฐ€๋ฆฌํ‚ค์ง€๋งŒ, ํ•ด์‹œ๋Š” ์ธ๋ฑ์‹ฑํ•œ๋‹ค.

ยง15 (ํ•ด์‹œ๋Š” ํ• ๋‹น๊ณผ ๋ฌด๊ด€) + ยง16 (ํ•ด์‹œ โ‰  ํฌ์ธํ„ฐ) โ€” ๋‘ ์งˆ๋ฌธ ๋ชจ๋‘ ํ•ต์‹ฌ์€ โ€œํ•ด์‹œ๋Š” ์œ„์น˜ ์ธ๋ฑ์Šค๋ฅผ ์œ„ํ•œ ๊ฒฐ์ •์  ์ •์ˆ˜โ€ ๋ผ๋Š” ์ •์˜ ํ•œ ์ค„๋กœ ์ˆ˜๋ ดํ•œ๋‹ค.


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

  • 14_std_map.md โ€” ๋ณธ ๋ฌธ์„œ์˜ ์›๋ณธ. ๋‹ต๋ณ€ ๊ทผ๊ฑฐ๊ฐ€ ๋ชจ๋‘ ์—ฌ๊ธฐ์— ์žˆ์Œ.
  • 13_vector_vs_list.md โ€” ๋…ธ๋“œ ์•ˆ์ •์„ฑยท์บ์‹œ ์นœํ™”์„ฑ ํ”„๋ ˆ์ž„. ยง9 ๊ฒŒ์ž„ ์—”์ง„ ์ฒ ํ•™๊ณผ ์ง๊ฒฐ.
  • 11_smart_pointer.md โ€” try_emplace + unique_ptr ์•ˆ์ „ ํŒจํ„ด + ํž™ ์ˆ˜๋ช… ์ž๋™ํ™”.
  • 03_new_vs_malloc.md โ€” ํž™ ๋ฉ”๋ชจ๋ฆฌ ์˜์—ญ (ยง7-1, ยง14 ์™€ ์ง๊ฒฐ).
  • 10_pointer_deepdive.md โ€” rehash ํ›„ ๋Œ•๊ธ€๋ง ํฌ์ธํ„ฐ (ยง12-2 iterator ๋ฌดํšจํ™”์™€ ๊ฐ™์€ ๋งฅ๋ฝ).
์ด ๊ธฐ์‚ฌ๋Š” ์ €์ž‘๊ถŒ์ž์˜ CC BY 4.0 ๋ผ์ด์„ผ์Šค๋ฅผ ๋”ฐ๋ฆ…๋‹ˆ๋‹ค.

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

Powered by Jekyll with Chirpy theme

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