ํฌ์ŠคํŠธ

CS โ€” std map

CS โ€” std map

๐Ÿ“• 04/29 โ€” std::map (Red-Black Tree ๊ธฐ๋ฐ˜ ์ •๋ ฌ ์—ฐ๊ด€ ์ปจํ…Œ์ด๋„ˆ)

๋ชจ์˜๋ฉด์ ‘ ํ›„์† ์ฃผ์ œ: โ€œstd::map์€ ์–ด๋–ป๊ฒŒ ๋™์ž‘ํ•˜๋‚˜์š”? unordered_map๊ณผ ์–ด๋–ป๊ฒŒ ๋‹ค๋ฅธ๊ฐ€์š”?โ€ Red-Black Tree โ†’ 5๊ฐ€์ง€ ์†์„ฑ๊ณผ ํšŒ์ „ โ†’ O(log n) ๋ณด์žฅ โ†’ ํ•ด์‹œ๋งต๊ณผ์˜ ๋น„๊ต โ†’ ์บ์‹œ ์นœํ™”์„ฑยท๋ฉ”๋ชจ๋ฆฌ ์˜ค๋ฒ„ํ—ค๋“œ โ†’ ์–ธ๋ฆฌ์–ผ TMap/TSortedMap ๊ผฌ๋ฆฌ์งˆ๋ฌธ ์—ฐ๊ฒฐ ๋‹ค๋ฆฌ


ํ•™์Šต ์˜์—ญ ์ „ํ™˜์  โ€” ์‹œํ€€์Šค์—์„œ ์—ฐ๊ด€ ์ปจํ…Œ์ด๋„ˆ๋กœ

13๋ฒˆ์—์„œ ์‹œํ€€์Šค ์ปจํ…Œ์ด๋„ˆ(vector vs list) ์˜ ๋ฉ”๋ชจ๋ฆฌ ๋ ˆ์ด์•„์›ƒ๊ณผ ์บ์‹œ ์นœํ™”์„ฑ์„ ๋‹ค๋ค˜๋‹ค๋ฉด, 14๋ฒˆ๋ถ€ํ„ฐ๋Š” ์—ฐ๊ด€ ์ปจํ…Œ์ด๋„ˆ(Associative Container) ์˜ ๊ฒ€์ƒ‰ ์ž๋ฃŒ๊ตฌ์กฐ ์˜์—ญ์œผ๋กœ ๋„˜์–ด์˜ต๋‹ˆ๋‹ค.

1
2
3
4
13๋ฒˆ  std::vector vs std::list                โ€” ์‹œํ€€์Šค: ์—ฐ์† ๋ฉ”๋ชจ๋ฆฌ vs ๋ถ„์‚ฐ ๋…ธ๋“œ + CPU ์บ์‹œ
โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€
14๋ฒˆ  std::map                                โ€” ์—ฐ๊ด€: ์ •๋ ฌ ํŠธ๋ฆฌ (Red-Black Tree) โ˜…
์ดํ›„  std::unordered_map / ํ•ด์‹œ ์ถฉ๋Œ / ์ •๋ ฌ   โ€” ํ•ด์‹œ ์ž๋ฃŒ๊ตฌ์กฐ + ์•Œ๊ณ ๋ฆฌ์ฆ˜ ์˜์—ญ

13๋ฒˆ์ด โ€œ๋ฉ”๋ชจ๋ฆฌ ๋ ˆ์ด์•„์›ƒ์ด ์บ์‹œ ์„ฑ๋Šฅ์„ ๊ฒฐ์ •ํ•œ๋‹คโ€ ์˜€๋‹ค๋ฉด, 14๋ฒˆ์€ โ€œ๊ฐ™์€ ํ‚ค-๊ฐ’ ์ €์žฅ์†Œ๋ผ๋„ ์ •๋ ฌ ํŠธ๋ฆฌ(O(log n) ๋ณด์žฅ) ์™€ ํ•ด์‹œ ํ…Œ์ด๋ธ”(ํ‰๊ท  O(1)) ์€ ํŠธ๋ ˆ์ด๋“œ์˜คํ”„๊ฐ€ ์ •๋ฐ˜๋Œ€โ€ ๋ผ๋Š” ์ ์ด ํ•ต์‹ฌ์ž…๋‹ˆ๋‹ค. ๋ฉด์ ‘์—์„œ๋Š” ๊ฑฐ์˜ ํ•ญ์ƒ map vs unordered_map ์ด ํ•œ ์„ธํŠธ๋กœ ๋‚˜์˜ต๋‹ˆ๋‹ค.


๋ชจ์˜๋ฉด์ ‘ ๋‹ต๋ณ€

std::map์€ ์ •๋ ฌ๋œ ์—ฐ๊ด€ ์ปจํ…Œ์ด๋„ˆ๋กœ, ํ‚ค-๊ฐ’ ์Œ์„ ํ‚ค ๊ธฐ์ค€์œผ๋กœ ์ž๋™ ์ •๋ ฌํ•ด ์ €์žฅํ•ฉ๋‹ˆ๋‹ค. ๋‚ด๋ถ€ ์ž๋ฃŒ๊ตฌ์กฐ๋Š” ๊ฑฐ์˜ ๋ชจ๋“  ํ‘œ์ค€ ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ ๊ตฌํ˜„์—์„œ Red-Black Tree (์ž๊ธฐ ๊ท ํ˜• ์ด์ง„ ํƒ์ƒ‰ ํŠธ๋ฆฌ) ์ž…๋‹ˆ๋‹ค. ํ‚ค ์ค‘๋ณต์€ ํ—ˆ์šฉํ•˜์ง€ ์•Š๊ณ , <map> ํ—ค๋”์— std::map<Key, Value, Compare, Allocator> ํ…œํ”Œ๋ฆฟ์œผ๋กœ ์ •์˜๋ฉ๋‹ˆ๋‹ค.

Red-Black Tree๋Š” ๊ฐ ๋…ธ๋“œ์— ๋นจ๊ฐ•ยท๊ฒ€์ • ์ƒ‰๊น”์„ ๋ถ€์—ฌํ•˜๊ณ  5๊ฐ€์ง€ ์†์„ฑ์„ ์œ ์ง€ํ•ด ํŠธ๋ฆฌ ๋†’์ด๋ฅผ ํ•ญ์ƒ O(log n) ์œผ๋กœ ๋ณด์žฅํ•ฉ๋‹ˆ๋‹ค. 1) ๋ชจ๋“  ๋…ธ๋“œ๋Š” ๋นจ๊ฐ• ๋˜๋Š” ๊ฒ€์ •, 2) ๋ฃจํŠธ๋Š” ๊ฒ€์ •, 3) ๋ชจ๋“  NIL(๋ฆฌํ”„) ์€ ๊ฒ€์ •, 4) ๋นจ๊ฐ• ๋…ธ๋“œ์˜ ์ž์‹์€ ๋ฐ˜๋“œ์‹œ ๊ฒ€์ • (๋นจ๊ฐ• ์—ฐ์† ๊ธˆ์ง€), 5) ์ž„์˜ ๋…ธ๋“œ์—์„œ ํ›„์† NIL ๊นŒ์ง€์˜ ๊ฒฝ๋กœ๋งˆ๋‹ค ๊ฒ€์ • ๋…ธ๋“œ ๊ฐœ์ˆ˜๊ฐ€ ๋™์ผํ•ฉ๋‹ˆ๋‹ค(black height). ์‚ฝ์ž…ยท์‚ญ์ œ ์‹œ ํšŒ์ „(rotation) ๊ณผ ์ƒ‰ ๋ณ€๊ฒฝ(recoloring) ์œผ๋กœ ์ด ์†์„ฑ์„ ๋ณต๊ตฌํ•ฉ๋‹ˆ๋‹ค. ๊ทธ๋ž˜์„œ insertยทeraseยทfind ๋ชจ๋‘ O(log n) ์ตœ์•… ๋ณด์žฅ์ž…๋‹ˆ๋‹ค.

๋น„์Šทํ•œ ์ž๊ธฐ ๊ท ํ˜• BST ์ธ AVL ํŠธ๋ฆฌ์™€ ๋น„๊ตํ•˜๋ฉด, AVL ์€ ๋” ์—„๊ฒฉํ•œ ๊ท ํ˜•(๋†’์ด ์ฐจ 1 ์ดํ•˜)์œผ๋กœ ๊ฒ€์ƒ‰์ด ์•ฝ๊ฐ„ ๋น ๋ฅด์ง€๋งŒ ํšŒ์ „ ํšŸ์ˆ˜๊ฐ€ ๋งŽ์•„ ์‚ฝ์ž…ยท์‚ญ์ œ๊ฐ€ ๋А๋ฆฝ๋‹ˆ๋‹ค. RB ํŠธ๋ฆฌ๋Š” ๊ท ํ˜•์ด ์•ฝ๊ฐ„ ๋А์Šจํ•œ ๋Œ€์‹  ํšŒ์ „์ด ์ ์–ด ์‚ฝ์ž…ยท์‚ญ์ œ ์œ„์ฃผ ์›Œํฌ๋กœ๋“œ์—์„œ ์œ ๋ฆฌํ•ฉ๋‹ˆ๋‹ค. ๊ทธ๋ž˜์„œ STL ์˜ mapยทset ์€ RB ํŠธ๋ฆฌ๋ฅผ ์ฑ„ํƒํ–ˆ์Šต๋‹ˆ๋‹ค.

std::unordered_map ์€ ํ•ด์‹œ ํ…Œ์ด๋ธ” ๊ธฐ๋ฐ˜์œผ๋กœ ํ‰๊ท  O(1) ์กฐํšŒยท์‚ฝ์ž…ยท์‚ญ์ œ๋ฅผ ์ œ๊ณตํ•˜์ง€๋งŒ ์ •๋ ฌ์ด ์•ˆ ๋˜๊ณ  ์ตœ์•…์€ O(n) ์ž…๋‹ˆ๋‹ค(ํ•ด์‹œ ์ถฉ๋Œ). ๋ฉ”๋ชจ๋ฆฌ ์˜ค๋ฒ„ํ—ค๋“œ๋„ ๋ฒ„ํ‚ท ๋ฐฐ์—ด + ๋…ธ๋“œ๋กœ ๋” ํฝ๋‹ˆ๋‹ค. map ์€ ํ‚ค ์ •๋ ฌยท๋ฒ”์œ„ ์กฐํšŒยทO(log n) ์ตœ์•… ๋ณด์žฅ์ด ํ•„์š”ํ•  ๋•Œ, unordered_map ์€ ์ˆœ์„œ ๋ฌด๊ด€ + ์ตœ๋Œ€ ์ฒ˜๋ฆฌ๋Ÿ‰์ด ์ค‘์š”ํ•  ๋•Œ ์„ ํƒํ•ฉ๋‹ˆ๋‹ค.

iterator ๋ฌดํšจํ™” ๊ทœ์น™์€ vector ์™€ ์ •๋ฐ˜๋Œ€๋กœ ๊น”๋”ํ•ฉ๋‹ˆ๋‹ค. map ์€ ์‚ฝ์ž… ์‹œ ๋‹ค๋ฅธ iterator ๊ฐ€ ๋ฌดํšจํ™”๋˜์ง€ ์•Š๊ณ , ์‚ญ์ œ ์‹œ์—๋„ ์‚ญ์ œ๋œ ๋…ธ๋“œ์˜ iterator ๋งŒ ๋ฌดํšจํ™”๋ฉ๋‹ˆ๋‹ค. ์ด๋Š” list ์™€ ๊ฐ™์€ ๋…ธ๋“œ ์•ˆ์ •์„ฑ์œผ๋กœ, RB ํŠธ๋ฆฌ๊ฐ€ ๋…ธ๋“œ๋ฅผ ํž™์— ๋ถ„์‚ฐ ํ• ๋‹นํ•˜๊ธฐ ๋•Œ๋ฌธ์— ์ž์—ฐ์Šค๋Ÿฝ๊ฒŒ ๋”ฐ๋ผ์˜ต๋‹ˆ๋‹ค. ๋‹จ, ๊ทธ ๋Œ€๊ฐ€๋กœ ์บ์‹œ ์นœํ™”์„ฑ์ด ๋–จ์–ด์ ธ vector ๋ณด๋‹ค ์ˆœํšŒ๊ฐ€ ๋А๋ฆฝ๋‹ˆ๋‹ค.

์–ธ๋ฆฌ์–ผ์—์„œ๋Š” STL map ์— ์ง์ ‘ ๋Œ€์‘ํ•˜๋Š” 1๊ธ‰ ์ปจํ…Œ์ด๋„ˆ๊ฐ€ ์—†์Šต๋‹ˆ๋‹ค. TMap ์€ ํ•ด์‹œ ๊ธฐ๋ฐ˜(unordered_map ๋Œ€์‘) ์ด๊ณ , ์ •๋ ฌ์ด ํ•„์š”ํ•˜๋ฉด TSortedMap ์„ ์‚ฌ์šฉํ•ฉ๋‹ˆ๋‹ค. ๊ฒŒ์ž„ ์—”์ง„ ํŠน์„ฑ์ƒ ์บ์‹œ ์นœํ™”์„ฑ์ด ์šฐ์„ ์ด๋ผ RB ํŠธ๋ฆฌ ์ปจํ…Œ์ด๋„ˆ๋Š” ์˜๋„์ ์œผ๋กœ ๋‘์ง€ ์•Š์€ ๊ฒƒ์ž…๋‹ˆ๋‹ค.


ํ•ต์‹ฌ ๊ฐœ๋…

๋ถ„๋ฅ˜ํ‚ค์›Œ๋“œํ•œ ์ค„ ์ •์˜
์—ฐ๊ด€ ์ปจํ…Œ์ด๋„ˆstd::mapRB-Tree ๊ธฐ๋ฐ˜ ์ •๋ ฌ๋œ ํ‚ค-๊ฐ’ ์ปจํ…Œ์ด๋„ˆ. ํ‚ค ์ค‘๋ณต ๋ถˆ๊ฐ€
ย std::setRB-Tree ๊ธฐ๋ฐ˜ ์ •๋ ฌ๋œ ํ‚ค ์ง‘ํ•ฉ. value ์—†์Œ
ย std::multimap๋™์ผ ํ‚ค ์ค‘๋ณต ํ—ˆ์šฉ. equal_range ๋กœ ๋ฒ”์œ„ ์กฐํšŒ
ย std::multiset๋™์ผ ํ‚ค ์ค‘๋ณต ํ—ˆ์šฉ set
ย std::unordered_mapํ•ด์‹œ ํ…Œ์ด๋ธ” ๊ธฐ๋ฐ˜. ํ‰๊ท  O(1), ์ˆœ์„œ ์—†์Œ
ย std::unordered_setํ•ด์‹œ ํ…Œ์ด๋ธ” ๊ธฐ๋ฐ˜ ํ‚ค ์ง‘ํ•ฉ
ย std::unordered_multimap / _multisetํ•ด์‹œ + ์ค‘๋ณต ํ—ˆ์šฉ
์ž๊ธฐ ๊ท ํ˜• BSTRed-Black Tree๋…ธ๋“œ ์ƒ‰๊น” 5์†์„ฑ์œผ๋กœ ๋†’์ด O(log n) ๋ณด์žฅ
ย AVL Tree๋†’์ด ์ฐจ 1 ์ดํ•˜ ์—„๊ฒฉ ๊ท ํ˜•. ํšŒ์ „ ์žฆ์Œ
ย black height์ž„์˜ ๋…ธ๋“œ์—์„œ NIL ๊นŒ์ง€ ๊ฒฝ๋กœ์˜ ๊ฒ€์ • ๋…ธ๋“œ ์ˆ˜
ย NIL ๋…ธ๋“œ๋ฆฌํ”„ (์‹ค์ œ ์ž์‹์ด ์—†๋Š” ์œ„์น˜). ํ•ญ์ƒ ๊ฒ€์ •
ย ํšŒ์ „ (Rotation)์ขŒํšŒ์ „/์šฐํšŒ์ „ โ€” ๋ถ€๋ชจ-์ž์‹ ๊ด€๊ณ„ ์žฌ๋ฐฐ์น˜
ย ์žฌ์ƒ‰์น  (Recoloring)์ƒ‰๊น”๋งŒ ๋ฐ”๊ฟ” ์†์„ฑ ๋ณต๊ตฌ (ํšŒ์ „ ์—†์ด)
ํ•ด์‹œ ํ…Œ์ด๋ธ”๋ฒ„ํ‚ท (Bucket)ํ•ด์‹œ๊ฐ’์œผ๋กœ ๋งคํ•‘๋˜๋Š” ์Šฌ๋กฏ. ๋ฐฐ์—ด๋กœ ๊ด€๋ฆฌ
ย ํ•ด์‹œ ํ•จ์ˆ˜ (Hash Function)ํ‚ค โ†’ ์ •์ˆ˜ ๋งคํ•‘. ๊ท ๋“ฑ ๋ถ„ํฌ๊ฐ€ ํ•ต์‹ฌ
ย ์ถฉ๋Œ (Collision)๋‹ค๋ฅธ ํ‚ค๊ฐ€ ๊ฐ™์€ ๋ฒ„ํ‚ท์— ๋งคํ•‘๋จ. ์ฒด์ด๋‹/์˜คํ”ˆ ์–ด๋“œ๋ ˆ์‹ฑ์œผ๋กœ ํ•ด๊ฒฐ
ย ์ฒด์ด๋‹ (Separate Chaining)๊ฐ™์€ ๋ฒ„ํ‚ท์˜ ์›์†Œ๋ฅผ ์—ฐ๊ฒฐ ๋ฆฌ์ŠคํŠธ๋กœ ๋ฌถ์Œ (STL ์ฑ„ํƒ)
ย ๋กœ๋“œ ํŒฉํ„ฐ (Load Factor)size / bucket_count. ์ดˆ๊ณผ ์‹œ rehash
ย rehash๋ฒ„ํ‚ท ๋ฐฐ์—ด ํ™•์žฅ + ๋ชจ๋“  ์›์†Œ ์žฌ๋ฐฐ์น˜ โ€” O(n)
์‹œ๊ฐ„ ๋ณต์žก๋„O(log n)map ๋ชจ๋“  ํ•ต์‹ฌ ์—ฐ์‚ฐ. ํŠธ๋ฆฌ ๋†’์ด์— ๋น„๋ก€
ย O(1) ํ‰๊ท unordered_map ์˜ ์กฐํšŒยท์‚ฝ์ž…ยท์‚ญ์ œ
ย O(n) ์ตœ์•…unordered_map ํ•ด์‹œ ์ถฉ๋Œ ์‹œ
iterator ์•ˆ์ •์„ฑ๋…ธ๋“œ ์•ˆ์ •์„ฑmap ์€ ์‚ญ์ œ๋œ ๋…ธ๋“œ๋งŒ ๋ฌดํšจ, ๋‚˜๋จธ์ง€ ์•ˆ์ „ (list ์™€ ๋™์ผ)
ย rehash ๋ฌดํšจํ™”unordered_map rehash ์‹œ ๋ชจ๋“  iterator ๋ฌดํšจํ™”
๋ฉ”๋ชจ๋ฆฌ ์˜ค๋ฒ„ํ—ค๋“œmap ๋…ธ๋“œ ํฌ๊ธฐ๋ถ€๋ชจ 8B + ์ขŒ 8B + ์šฐ 8B + ์ƒ‰ + ํ‚ค-๊ฐ’ + ํž™ ํ—ค๋” ~16B
ย unordered_map ์˜ค๋ฒ„ํ—ค๋“œ๋ฒ„ํ‚ท ๋ฐฐ์—ด + ์ฒด์ด๋‹ ๋…ธ๋“œ (next ํฌ์ธํ„ฐ)
์ฝ”๋“œ ๊ด€์šฉ๊ตฌoperator[]ํ‚ค ์—†์œผ๋ฉด default ์‚ฝ์ž… (mutating). const ์—์„œ ๋ชป ์”€
ย find vs countfind ๋Š” iterator, count ๋Š” 0 ๋˜๋Š” 1 (multimap ์—์„œ๋งŒ ์˜๋ฏธ)
ย emplacein-place ์ƒ์„ฑ โ€” ์ž„์‹œ ๊ฐ์ฒด ํšŒํ”ผ
ย try_emplace (C++17)ํ‚ค ์žˆ์œผ๋ฉด ์•„๋ฌด ์ผ๋„ ์•ˆ ํ•จ โ€” operator[] ๋ณด๋‹ค ์•ˆ์ „
ย insert_or_assign (C++17)์žˆ์œผ๋ฉด ๋Œ€์ž…, ์—†์œผ๋ฉด ์‚ฝ์ž… โ€” ๋ช…ํ™•ํ•œ ์˜๋„
ย structured binding (C++17)for (auto& [k, v] : m)
์–ธ๋ฆฌ์–ผ ์ปจํ…Œ์ด๋„ˆTMapํ•ด์‹œ ๊ธฐ๋ฐ˜ โ€” STL unordered_map ๋Œ€์‘
ย TSortedMap์ •๋ ฌ ๊ธฐ๋ฐ˜์ด์ง€๋งŒ RB-Tree ๊ฐ€ ์•„๋‹Œ ์ •๋ ฌ๋œ ๋ฐฐ์—ด
ย TMultiMapํ‚ค ์ค‘๋ณต ํ—ˆ์šฉ

๋ชฉ์ฐจ

  1. ํ•ต์‹ฌ ์š”์•ฝ ์นด๋“œ
  2. std::map ์ด๋ž€ โ€” ์ •๋ ฌ๋œ ์—ฐ๊ด€ ์ปจํ…Œ์ด๋„ˆ
  3. ๋‚ด๋ถ€ ๋™์ž‘ โ€” Red-Black Tree
  4. ์ฃผ์š” ์—ฐ์‚ฐ๊ณผ ์‹œ๊ฐ„ ๋ณต์žก๋„
  5. iterator ๋ฌดํšจํ™” ๊ทœ์น™ (vectorยทlist ์™€ ๋น„๊ต)
  6. ์œ ์‚ฌํ•œ ๋ฒ”์œ„์˜ ๋‹ค๋ฅธ ์ปจํ…Œ์ด๋„ˆ โ€” set / multimap / unordered_*
  7. ์ฝ”๋“œ ์˜ˆ์ œ โ€” ๊ธฐ๋ณธ ์‚ฌ์šฉ / Custom Compare / emplace
  8. ๋ฉด์ ‘ ๋‹จ๊ณจ ๊ผฌ๋ฆฌ๋ฌผ๊ธฐ
  9. ์–ธ๋ฆฌ์–ผ TMap vs STL
  10. ํšŒ๊ท€ ๋‹ค๋ฆฌ โ€” ๋‹ค๋ฅธ CS ํŒŒ์ผ ์—ฐ๊ฒฐ
  11. ๊ผฌ๋ฆฌ์งˆ๋ฌธ ์˜ˆ์ƒ ๊ฒฝ๋กœ
  12. ๋ชจ์˜๋ฉด์ ‘ ๋‹ต๋ณ€ ํ…œํ”Œ๋ฆฟ (1๋ถ„ / 3๋ถ„)

1. ํ•ต์‹ฌ ์š”์•ฝ ์นด๋“œ

ํ•œ ์ค„ ์š”์•ฝ 30์ดˆ

1
2
3
4
5
6
7
std::map      โ€” RB-Tree ๊ธฐ๋ฐ˜ ์ •๋ ฌ ์—ฐ๊ด€ ์ปจํ…Œ์ด๋„ˆ.
                 insert/erase/find ๋ชจ๋‘ O(log n) ์ตœ์•… ๋ณด์žฅ.
                 ํ‚ค ์ค‘๋ณต ๋ถˆ๊ฐ€, ํ‚ค ์ž๋™ ์ •๋ ฌ, ๋…ธ๋“œ ์•ˆ์ •์„ฑ (์‚ญ์ œ ๋…ธ๋“œ๋งŒ ๋ฌดํšจ).
unordered_map โ€” ํ•ด์‹œ ํ…Œ์ด๋ธ” ๊ธฐ๋ฐ˜. ํ‰๊ท  O(1), ์ตœ์•… O(n), ์ˆœ์„œ ์—†์Œ.

์„ ํƒ ๋ฃฐ      โ€” ์ •๋ ฌยท๋ฒ”์œ„ ์กฐํšŒยท์ตœ์•… ๋ณด์žฅ ํ•„์š” โ†’ map
              ์ˆœ์„œ ๋ฌด๊ด€ยท์ตœ๋Œ€ ์ฒ˜๋ฆฌ๋Ÿ‰ โ†’ unordered_map

์‹œ๊ฐ„ ๋ณต์žก๋„ ํ‘œ 30์ดˆ

์—ฐ์‚ฐmapunordered_map
insertO(log n)ํ‰๊ท  O(1), ์ตœ์•… O(n)
eraseO(log n)ํ‰๊ท  O(1), ์ตœ์•… O(n)
findO(log n)ํ‰๊ท  O(1), ์ตœ์•… O(n)
operator[]O(log n)ํ‰๊ท  O(1)
์ˆœํšŒ begin โ†’ endO(n) (์ •๋ ฌ ์ˆœ)O(n) (์ˆœ์„œ ์—†์Œ)
๋ฒ”์œ„ ์กฐํšŒ (lower/upper_bound)O(log n) โ˜…์ง€์› ์•ˆ ํ•จ

Red-Black Tree 5์†์„ฑ 30์ดˆ

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

โ†’ ํŠธ๋ฆฌ ๋†’์ด๊ฐ€ ์ตœ์•… 2 log(n+1) ๋กœ ์ œํ•œ
โ†’ insert/erase/find ๋ชจ๋‘ O(log n) ๋ณด์žฅ

๊ผฌ๋ฆฌ์งˆ๋ฌธ ์—ฐ๊ฒฐ ๋งต

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
std::map
โ”œโ”€โ”€ ๋‚ด๋ถ€ ๋™์ž‘ โ€” Red-Black Tree
โ”‚   โ”œโ”€โ”€ 5๊ฐ€์ง€ ์†์„ฑ (R/B ์ƒ‰๊น” ๊ทœ์น™)
โ”‚   โ”œโ”€โ”€ ํšŒ์ „ (LL, RR, LR, RL) + ์žฌ์ƒ‰์น 
โ”‚   โ””โ”€โ”€ AVL ๊ณผ ๋น„๊ต (ํšŒ์ „ ํšŸ์ˆ˜ ํŠธ๋ ˆ์ด๋“œ์˜คํ”„)
โ”œโ”€โ”€ ์‹œ๊ฐ„ ๋ณต์žก๋„ O(log n) ๋ณด์žฅ
โ”‚   โ””โ”€โ”€ operator[] / find / lower_bound / upper_bound
โ”œโ”€โ”€ iterator ๋ฌดํšจํ™” (โ˜… 13๋ฒˆ ํšŒ๊ท€)
โ”‚   โ”œโ”€โ”€ ์‚ฝ์ž… โ€” ๋ฌดํšจํ™” ์—†์Œ
โ”‚   โ””โ”€โ”€ ์‚ญ์ œ โ€” ์‚ญ์ œ๋œ ๋…ธ๋“œ๋งŒ ๋ฌดํšจ
โ”œโ”€โ”€ unordered_map ๋น„๊ต โ˜… ๊ฐ€์žฅ ์ค‘์š”ํ•œ ๊ผฌ๋ฆฌ๋ฌผ๊ธฐ
โ”‚   โ”œโ”€โ”€ ํ•ด์‹œ ํ…Œ์ด๋ธ” (๋ฒ„ํ‚ท + ์ฒด์ด๋‹)
โ”‚   โ”œโ”€โ”€ ํ‰๊ท  O(1) vs ์ตœ์•… O(n)
โ”‚   โ””โ”€โ”€ ์บ์‹œ ์นœํ™”์„ฑ / ๋ฉ”๋ชจ๋ฆฌ ์˜ค๋ฒ„ํ—ค๋“œ
โ”œโ”€โ”€ set / multimap / multiset
โ”‚   โ””โ”€โ”€ equal_range ๋กœ ๋™์ผ ํ‚ค ๋ฒ”์œ„ ์กฐํšŒ
โ”œโ”€โ”€ ์ฝ”๋“œ ๊ด€์šฉ๊ตฌ
โ”‚   โ”œโ”€โ”€ operator[] vs find vs at
โ”‚   โ”œโ”€โ”€ emplace vs insert vs try_emplace (C++17)
โ”‚   โ””โ”€โ”€ insert_or_assign / structured binding
โ””โ”€โ”€ ์–ธ๋ฆฌ์–ผ
    โ”œโ”€โ”€ TMap (ํ•ด์‹œ) โ€” STL unordered_map ๋Œ€์‘
    โ”œโ”€โ”€ TSortedMap (์ •๋ ฌ ๋ฐฐ์—ด, RB ์•„๋‹˜)
    โ””โ”€โ”€ ๊ฒŒ์ž„ ์—”์ง„์€ RB ํŠธ๋ฆฌ ํšŒํ”ผ โ€” ์บ์‹œ ์นœํ™” ์šฐ์„ 

2. std::map ์ด๋ž€ โ€” ์ •๋ ฌ๋œ ์—ฐ๊ด€ ์ปจํ…Œ์ด๋„ˆ

ํ•ต์‹ฌ ํ•œ ๋ฌธ์žฅ

std::map ์€ ํ‚ค ๊ธฐ์ค€์œผ๋กœ ์ž๋™ ์ •๋ ฌ๋˜๋Š” ํ‚ค-๊ฐ’ ์Œ ์ปจํ…Œ์ด๋„ˆ์ด๋ฉฐ, ๋‚ด๋ถ€์ ์œผ๋กœ Red-Black Tree ๋ฅผ ์จ์„œ ๋ชจ๋“  ํ•ต์‹ฌ ์—ฐ์‚ฐ์ด O(log n) ์ตœ์•… ๋ณด์žฅ๋ฉ๋‹ˆ๋‹ค.

2-1. ๊ธฐ๋ณธ ์ •์˜

1
2
3
4
5
6
template<
    class Key,
    class T,
    class Compare = std::less<Key>,
    class Allocator = std::allocator<std::pair<const Key, T>>
> class map;
  • Key โ€” ํ‚ค ํƒ€์ž… (์ •๋ ฌ๋˜์–ด์•ผ ํ•จ)
  • T โ€” ๊ฐ’ ํƒ€์ž…
  • Compare โ€” ์ •๋ ฌ ๊ธฐ์ค€. ๊ธฐ๋ณธ์€ std::less<Key> (์˜ค๋ฆ„์ฐจ์ˆœ)
  • Allocator โ€” ๋ฉ”๋ชจ๋ฆฌ ํ• ๋‹น์ž
1
2
3
4
5
6
7
8
9
10
11
12
#include <map>
#include <string>

std::map<std::string, int> ages;
ages["Alice"] = 30;
ages["Bob"]   = 25;
ages["Carol"] = 35;

// ์ˆœํšŒ ์‹œ ์ž๋™์œผ๋กœ ํ‚ค ์ •๋ ฌ ์ˆœ์„œ: Alice โ†’ Bob โ†’ Carol
for (const auto& [name, age] : ages) {
    std::cout << name << ": " << age << "\n";
}

2-2. ํ‚ค ์ค‘๋ณต ๋ถˆ๊ฐ€, ์ž๋™ ์ •๋ ฌ

1
2
3
4
5
6
7
std::map<int, std::string> m;
m.insert({3, "three"});
m.insert({1, "one"});
m.insert({2, "two"});
m.insert({1, "ONE"});   // ๋ฌด์‹œ๋จ โ€” ํ‚ค 1 ์ด๋ฏธ ์กด์žฌ

// ์ˆœํšŒ ๊ฒฐ๊ณผ: (1, "one"), (2, "two"), (3, "three")
  • ๊ฐ™์€ ํ‚ค ๋‘ ๋ฒˆ ์‚ฝ์ž…ํ•˜๋ฉด ๋‘ ๋ฒˆ์งธ๋Š” ์‚ฝ์ž… ์‹คํŒจ (๊ฐ’์ด ๋ฎ์–ด์“ฐ์ด์ง€ ์•Š์Œ)
  • ๊ฐ’์„ ๋ฎ์–ด์“ฐ๋ ค๋ฉด m[1] = "ONE" ๋˜๋Š” insert_or_assign(1, "ONE") ์‚ฌ์šฉ

2-3. std::pair<const Key, T> ๊ฐ€ ์›์†Œ ํƒ€์ž…์ธ ์ด์œ 

1
2
3
using value_type = std::pair<const Key, T>;
//                          ^^^^^^^^^^^
//                          ํ‚ค๋Š” const โ€” ๋ณ€๊ฒฝ ๋ถˆ๊ฐ€
  • ํ‚ค๋ฅผ ๋ณ€๊ฒฝํ•˜๋ฉด ํŠธ๋ฆฌ ์ •๋ ฌ ์ˆœ์„œ๊ฐ€ ๊นจ์ง€๋ฏ€๋กœ const ๋กœ ๋ง‰์Œ
  • ๊ฐ’(T) ๋งŒ ๋ณ€๊ฒฝ ๊ฐ€๋Šฅ
1
2
3
auto it = m.find(1);
it->second = "modified";   // โœ… ๊ฐ’ ๋ณ€๊ฒฝ OK
it->first = 99;            // โŒ ์ปดํŒŒ์ผ ์—๋Ÿฌ โ€” const Key

2-4. ํ—ค๋”์™€ ํ‘œ์ค€ ์‹œ๊ทธ๋‹ˆ์ฒ˜

1
2
3
4
5
6
7
8
#include <map>           // map, multimap

namespace std {
    template <class Key, class T, class Compare, class Allocator>
    class map;
    template <class Key, class T, class Compare, class Allocator>
    class multimap;       // ํ‚ค ์ค‘๋ณต ํ—ˆ์šฉ
}

2-5. ์–ด๋””์— ์“ฐ๋Š”๊ฐ€

์‚ฌ์šฉ ์‚ฌ๋ก€์ด์œ 
์ •๋ ฌ๋œ ์‚ฌ์ „ (์ด๋ฆ„ โ†’ ๋‚˜์ด)ํ‚ค ์ž๋™ ์ •๋ ฌ, ์ˆœํšŒ ์‹œ ์ •๋ ฌ ์ˆœ์„œ
๋ฒ”์œ„ ์กฐํšŒ (ํŠน์ • ์‹œ๊ฐ„ ๋ฒ”์œ„์˜ ์ด๋ฒคํŠธ)lower_bound/upper_bound O(log n)
์ตœ์•… ์‹œ๊ฐ„ ๋ณด์žฅ์ด ํ•„์š”ํ•œ ์‹œ์Šคํ…œํ•ด์‹œ ์ถฉ๋Œ๋กœ ์ธํ•œ O(n) ์ŠคํŒŒ์ดํฌ ํšŒํ”ผ
ํ‚ค๊ฐ€ ๋ณต์žกํ•œ ๋น„๊ต ๊ฐ€๋Šฅ ๊ฐ์ฒดCompare ๋งŒ ์ •์˜ํ•˜๋ฉด ๋จ (ํ•ด์‹œ ํ•จ์ˆ˜ ๋ถˆํ•„์š”)
๋ณ€๊ฒฝ ๋นˆ๋„๊ฐ€ ์ ๊ณ  ์ •๋ ฌ ์ˆœํšŒ๊ฐ€ ์žฆ์ŒํŠธ๋ฆฌ ์ˆœํšŒ ์ž์ฒด๋Š” ๊น”๋”

ํ•ด์‹œ๊ฐ€ ๋” ์ ํ•ฉํ•œ ๊ฒฝ์šฐ:

  • ํ‚ค ์ •๋ ฌ์ด ํ•„์š” ์—†์Œ
  • ์ตœ๋Œ€ ์ฒ˜๋ฆฌ๋Ÿ‰์ด ์ค‘์š” (๊ฒŒ์ž„ ์—”์ง„, ์ธ๋ฉ”๋ชจ๋ฆฌ ์บ์‹œ)
  • ํ‚ค๊ฐ€ ํ•ด์‹œ ํ•จ์ˆ˜๋กœ ์ž˜ ๋ถ„ํฌ๋จ (์ •์ˆ˜, ๋ฌธ์ž์—ด ๋“ฑ)

3. ๋‚ด๋ถ€ ๋™์ž‘ โ€” Red-Black Tree

ํ•ต์‹ฌ ํ•œ ๋ฌธ์žฅ

Red-Black Tree ๋Š” ๊ฐ ๋…ธ๋“œ์— ๋นจ๊ฐ•ยท๊ฒ€์ • ์ƒ‰๊น”์„ ๋ถ€์—ฌํ•˜๊ณ  5๊ฐ€์ง€ ์†์„ฑ์„ ์œ ์ง€ํ•ด ํŠธ๋ฆฌ ๋†’์ด๋ฅผ O(log n) ์œผ๋กœ ๋ณด์žฅํ•˜๋Š” ์ž๊ธฐ ๊ท ํ˜• ์ด์ง„ ํƒ์ƒ‰ ํŠธ๋ฆฌ์ž…๋‹ˆ๋‹ค. STL mapยทset ์˜ ํ‘œ์ค€์  ๊ตฌํ˜„์ž…๋‹ˆ๋‹ค.

3-1. ์™œ ์ž๊ธฐ ๊ท ํ˜• BST ๊ฐ€ ํ•„์š”ํ•œ๊ฐ€

์ผ๋ฐ˜ ์ด์ง„ ํƒ์ƒ‰ ํŠธ๋ฆฌ(BST) ์˜ ๋ฌธ์ œ:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
์ˆœ์„œ๋Œ€๋กœ ์‚ฝ์ž…ํ•œ ๊ฒฝ์šฐ (1, 2, 3, 4, 5):

       1
        \
         2
          \
           3
            \
             4
              \
               5

โ†’ ํŠธ๋ฆฌ๊ฐ€ ํ•œ์ชฝ์œผ๋กœ ์น˜์šฐ์นจ (skewed)
โ†’ ๋†’์ด = n
โ†’ ๊ฒ€์ƒ‰์ด O(n) โ€” ์‚ฌ์‹ค์ƒ ์—ฐ๊ฒฐ ๋ฆฌ์ŠคํŠธ์™€ ๋™์ผ

์ž๊ธฐ ๊ท ํ˜• BST ๋Š” ์‚ฝ์ž…ยท์‚ญ์ œํ•  ๋•Œ๋งˆ๋‹ค ์ž๋™์œผ๋กœ ๊ท ํ˜•์„ ๋งž์ถฐ ๋†’์ด๋ฅผ O(log n) ์œผ๋กœ ์œ ์ง€ํ•ฉ๋‹ˆ๋‹ค.

1
2
3
4
5
6
7
8
9
RB-Tree ๋กœ ๊ฐ™์€ ๋ฐ์ดํ„ฐ ์‚ฝ์ž…:

         3
       /   \
      1     4
       \     \
        2     5

โ†’ ๋†’์ด 3 โ€” logโ‚‚(5) โ‰ˆ 2.3 ์ •๋„ ์ˆ˜์ค€

3-2. Red-Black Tree ์˜ 5๊ฐ€์ง€ ์†์„ฑ

1
2
3
4
5
6
7
8
์†์„ฑ 1) ๋ชจ๋“  ๋…ธ๋“œ๋Š” ๋นจ๊ฐ•(R) ๋˜๋Š” ๊ฒ€์ •(B)
์†์„ฑ 2) ๋ฃจํŠธ๋Š” ํ•ญ์ƒ ๊ฒ€์ •
์†์„ฑ 3) ๋ชจ๋“  NIL (๋ฆฌํ”„) ์€ ๊ฒ€์ •
        โ€” NIL ์€ ์‹ค์ œ ์ž์‹์ด ์—†๋Š” ์œ„์น˜๋ฅผ ๋‚˜ํƒ€๋‚ด๋Š” ๊ฐ€์ƒ ๋…ธ๋“œ
์†์„ฑ 4) ๋นจ๊ฐ• ๋…ธ๋“œ์˜ ์ž์‹์€ ๋ฐ˜๋“œ์‹œ ๊ฒ€์ •
        โ€” ๋นจ๊ฐ• ์—ฐ์† (R-R) ๊ธˆ์ง€
์†์„ฑ 5) ์ž„์˜์˜ ๋…ธ๋“œ์—์„œ ํ›„์† NIL ๊นŒ์ง€์˜ ๋ชจ๋“  ๊ฒฝ๋กœ์— ๋Œ€ํ•ด
        ๊ฒ€์ • ๋…ธ๋“œ ๊ฐœ์ˆ˜๊ฐ€ ๋™์ผ (black height)

์‹œ๊ฐ์  ์˜ˆ์‹œ

1
2
3
4
5
6
7
8
9
10
11
         [10:B]                  โ† ๋ฃจํŠธ๋Š” ๊ฒ€์ • (์†์„ฑ 2)
        /      \
     [5:R]    [15:R]             โ† ๋นจ๊ฐ• ๋…ธ๋“œ. ์ž์‹์€ ๋ชจ๋‘ ๊ฒ€์ •์ด์–ด์•ผ ํ•จ (์†์„ฑ 4)
     /  \      /  \
  [3:B][7:B][12:B][20:B]         โ† ๊ฒ€์ • ๋…ธ๋“œ๋“ค
   / \  / \  / \   / \
  N  N N  N N  N  N  N           โ† NIL ๋…ธ๋“œ (๋ชจ๋‘ ๊ฒ€์ •, ์†์„ฑ 3)

๊ฐ ๋…ธ๋“œ โ†’ NIL ๊นŒ์ง€์˜ black height:
  10 โ†’ ์–ด๋–ค NIL: ๊ฒ€์ • = 2๊ฐœ (์ž๊ธฐ ์ž์‹  ํฌํ•จ ์•ˆ ํ•จ, ๋˜๋Š” ํฌํ•จ)
  โ†’ ๋ชจ๋“  ๊ฒฝ๋กœ ๋™์ผ (์†์„ฑ 5) โœ“

์†์„ฑ์ด ๋ณด์žฅํ•˜๋Š” ๊ฒƒ โ€” ๋†’์ด โ‰ค 2 log(n+1)

  • ์†์„ฑ 4: R-R ๊ธˆ์ง€ โ†’ ์–ด๋–ค ๊ฒฝ๋กœ๋„ ์ ˆ๋ฐ˜ ์ด์ƒ์ด ๋นจ๊ฐ•์ผ ์ˆ˜ ์—†์Œ
  • ์†์„ฑ 5: ๋ชจ๋“  ๊ฒฝ๋กœ์˜ ๊ฒ€์ • ์ˆ˜ ๋™์ผ โ†’ ๊ฒ€์ • ๊ฒฝ๋กœ ๊ธธ์ด ์ผ์ •
  • ๊ฒฐ๊ณผ: ๊ฐ€์žฅ ์งง์€ ๊ฒฝ๋กœ(์ „๋ถ€ ๊ฒ€์ •) vs ๊ฐ€์žฅ ๊ธด ๊ฒฝ๋กœ(R-B ๊ต๋Œ€) ์˜ ๊ธธ์ด ์ฐจ์ด๊ฐ€ 2๋ฐฐ ์ด๋‚ด
1
2
3
4
5
6
๊ฐ€์žฅ ์งง์€ ๊ฒฝ๋กœ: B - B - B - ... (๊ฒ€์ •๋งŒ)
๊ฐ€์žฅ ๊ธด ๊ฒฝ๋กœ:  R - B - R - B - ... (R/B ๊ต๋Œ€)

โ†’ ๊ธด ๊ฒฝ๋กœ โ‰ค ์งง์€ ๊ฒฝ๋กœ ร— 2
โ†’ ํŠธ๋ฆฌ ๋†’์ด h โ‰ค 2 logโ‚‚(n+1)
โ†’ ๋ชจ๋“  ์—ฐ์‚ฐ O(log n) ๋ณด์žฅ

3-3. ์‚ฝ์ž… โ€” ํšŒ์ „๊ณผ ์žฌ์ƒ‰์น 

์ƒˆ ๋…ธ๋“œ๋Š” ํ•ญ์ƒ ๋นจ๊ฐ•์œผ๋กœ ์‚ฝ์ž…ํ•ฉ๋‹ˆ๋‹ค (์†์„ฑ 5: black height ๋ณ€ํ™” ์ตœ์†Œํ™”).

1
2
3
4
5
6
7
์‚ฝ์ž… ์•Œ๊ณ ๋ฆฌ์ฆ˜:
  1. BST ๊ทœ์น™์œผ๋กœ ์œ„์น˜ ์ฐพ๊ธฐ
  2. ์ƒˆ ๋…ธ๋“œ๋ฅผ ๋นจ๊ฐ•์œผ๋กœ ์‚ฝ์ž…
  3. ์†์„ฑ ์œ„๋ฐ˜ ๊ฒ€์‚ฌ โ†’ ์œ„๋ฐ˜์ด๋ฉด ๋ณต๊ตฌ ๋ฃจํ”„:
     - ๋ถ€๋ชจ๊ฐ€ ๊ฒ€์ •์ด๋ฉด ์•„๋ฌด ์ž‘์—… ์—†์ด ์ข…๋ฃŒ
     - ๋ถ€๋ชจ๊ฐ€ ๋นจ๊ฐ•์ด๊ณ  ์‚ผ์ดŒ๋„ ๋นจ๊ฐ• โ†’ ์žฌ์ƒ‰์น  (ํ• ์•„๋ฒ„์ง€๊ฐ€ ๋นจ๊ฐ•์ด ๋จ, ์œ„๋กœ ์ „ํŒŒ)
     - ๋ถ€๋ชจ๊ฐ€ ๋นจ๊ฐ•์ด๊ณ  ์‚ผ์ดŒ์ด ๊ฒ€์ • โ†’ ํšŒ์ „ + ์žฌ์ƒ‰์น 

ํšŒ์ „ 4๊ฐ€์ง€ ์ผ€์ด์Šค

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
LL (์™ผ์ชฝ ์ž์‹์˜ ์™ผ์ชฝ ์ž์‹์ด ๋นจ๊ฐ•):

       G(B)                     P(B)
      /    \                   /    \
    P(R)   U(B)    โ†’RRํšŒ์ „    X(R)  G(R)
    /                                  \
  X(R)                                 U(B)

LR (์™ผ์ชฝ ์ž์‹์˜ ์˜ค๋ฅธ์ชฝ ์ž์‹์ด ๋นจ๊ฐ•):

       G(B)                G(B)                   X(B)
      /    \              /    \                 /    \
    P(R)   U(B)  โ†’LR     X(R)  U(B)   โ†’RR     P(R)   G(R)
       \                  /                              \
       X(R)              P(R)                            U(B)

RL (์˜ค๋ฅธ์ชฝ์˜ ์™ผ์ชฝ ์ž์‹): LR ์˜ ๋Œ€์นญ
RR (์˜ค๋ฅธ์ชฝ์˜ ์˜ค๋ฅธ์ชฝ ์ž์‹): LL ์˜ ๋Œ€์นญ

ํ•ต์‹ฌ:

  • ํšŒ์ „(Rotation) ์€ BST ์†์„ฑ์„ ์œ ์ง€ํ•˜๋ฉด์„œ ๋ถ€๋ชจ-์ž์‹ ๊ด€๊ณ„๋ฅผ ์žฌ๋ฐฐ์น˜
  • ์žฌ์ƒ‰์น (Recoloring) ์€ ํšŒ์ „ ์—†์ด ์ƒ‰๊น”๋งŒ ๋ฐ”๊ฟ” ์†์„ฑ ๋ณต๊ตฌ
  • ์‚ฝ์ž… ์‹œ ํšŒ์ „์€ ์ตœ๋Œ€ 2๋ฒˆ (LR, RL ์ผ€์ด์Šค์—์„œ๋งŒ 2๋ฒˆ)

3-4. ์‚ญ์ œ โ€” ๋” ๋ณต์žกํ•œ ๋ณต๊ตฌ

์‚ญ์ œ๋Š” black height ๊ฐ€ ๊นจ์งˆ ์ˆ˜ ์žˆ์–ด ๋” ๊นŒ๋‹ค๋กญ์Šต๋‹ˆ๋‹ค.

1
2
3
4
5
6
7
์‚ญ์ œ ์•Œ๊ณ ๋ฆฌ์ฆ˜ ์š”์•ฝ:
  1. BST ๊ทœ์น™์œผ๋กœ ์‚ญ์ œํ•  ๋…ธ๋“œ ์ฐพ๊ธฐ
  2. ์ž์‹์ด 2๊ฐœ๋ฉด ํ›„์†์ž(successor) ์™€ ๊ฐ’ ๊ตํ™˜ โ†’ ์ž์‹ 0/1๊ฐœ ์ผ€์ด์Šค๋กœ ํ™˜์›
  3. ์‚ญ์ œํ•  ๋…ธ๋“œ๊ฐ€ ๋นจ๊ฐ• โ†’ ๊ทธ๋ƒฅ ์‚ญ์ œ (์†์„ฑ 5 ์˜ํ–ฅ ์—†์Œ)
  4. ์‚ญ์ œํ•  ๋…ธ๋“œ๊ฐ€ ๊ฒ€์ • โ†’ black height 1 ๊ฐ์†Œ โ†’ ๋ณต๊ตฌ ๋ฃจํ”„:
     - ํ˜•์ œ ๋…ธ๋“œ์˜ ์ƒ‰๊น”๊ณผ ์ž์‹๋“ค์— ๋”ฐ๋ผ 5๊ฐ€์ง€ ์ผ€์ด์Šค ๋ถ„๊ธฐ
     - ํšŒ์ „ + ์žฌ์ƒ‰์น ๋กœ black height ๋ณต๊ตฌ

์‚ญ์ œ ์‹œ ํšŒ์ „์€ ์ตœ๋Œ€ 3๋ฒˆ ์œผ๋กœ ์ œํ•œ๋ฉ๋‹ˆ๋‹ค.

3-5. ์™œ RB ํŠธ๋ฆฌ์ธ๊ฐ€ โ€” AVL ๊ณผ์˜ ๋น„๊ต

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

ํ•ต์‹ฌ ํŠธ๋ ˆ์ด๋“œ์˜คํ”„:

  • AVL โ€” ๊ฒ€์ƒ‰ ์œ„์ฃผ ์›Œํฌ๋กœ๋“œ์— ์œ ๋ฆฌ (๊ท ํ˜•์ด ์—„๊ฒฉํ•ด ํŠธ๋ฆฌ ๋†’์ด๊ฐ€ ์•ฝ๊ฐ„ ๋‚ฎ์Œ)
  • RB โ€” ์‚ฝ์ž…ยท์‚ญ์ œ ์œ„์ฃผ ์›Œํฌ๋กœ๋“œ์— ์œ ๋ฆฌ (ํšŒ์ „์ด ์ ์–ด ๊ฐฑ์‹  ๋น„์šฉ ๋‚ฎ์Œ)

STL map ์€ ์ผ๋ฐ˜ ๋ชฉ์ ์ด๊ณ  ์‚ฝ์ž…ยท์‚ญ์ œ๋„ ์ž์ฃผ ์ผ์–ด๋‚˜๋ฏ€๋กœ RB ํŠธ๋ฆฌ๋ฅผ ์ฑ„ํƒํ–ˆ์Šต๋‹ˆ๋‹ค.

3-6. ๋…ธ๋“œ ๋ฉ”๋ชจ๋ฆฌ ๋ ˆ์ด์•„์›ƒ

1
2
3
4
5
6
7
8
// libstdc++ ์˜ _Rb_tree_node ๋‹จ์ˆœํ™”
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
4
์ƒ‰๊น” + ๋ถ€๋ชจ + ์ขŒ + ์šฐ + (ํ‚ค 4B + ๊ฐ’ 4B + ํŒจ๋”ฉ 4B) + ํž™ ํ—ค๋” ~16B
โ‰ˆ 8 + 8 + 8 + 8 + 12 + 16 = 60๋ฐ”์ดํŠธ

๋ฐ์ดํ„ฐ 8๋ฐ”์ดํŠธ(int ํ‚ค+๊ฐ’) ๋ฅผ ์œ„ํ•ด 60๋ฐ”์ดํŠธ ์‚ฌ์šฉ โ†’ ํšจ์œจ ~13%

13๋ฒˆ list ์™€ ๋งˆ์ฐฌ๊ฐ€์ง€๋กœ ๋…ธ๋“œ ๋ถ„์‚ฐ + ํฐ ์˜ค๋ฒ„ํ—ค๋“œ โ€” ์บ์‹œ ์นœํ™”์„ฑ์ด vector ๋Œ€๋น„ ๋–จ์–ด์ง‘๋‹ˆ๋‹ค.


4. ์ฃผ์š” ์—ฐ์‚ฐ๊ณผ ์‹œ๊ฐ„ ๋ณต์žก๋„

ํ•ต์‹ฌ ํ•œ ๋ฌธ์žฅ

std::map ์˜ ๋ชจ๋“  ํ•ต์‹ฌ ์—ฐ์‚ฐ์€ ํŠธ๋ฆฌ ๋†’์ด O(log n) ์— ๋น„๋ก€ํ•˜๋ฉฐ, ์ด๊ฒŒ ํ•ด์‹œ๋งต์˜ ํ‰๊ท  O(1) ๊ณผ ๊ฐ€์žฅ ํฐ ์ฐจ์ด์ž…๋‹ˆ๋‹ค.

4-1. ์‹œ๊ฐ„ ๋ณต์žก๋„ ์ข…ํ•ฉ

์—ฐ์‚ฐ๋ณต์žก๋„๋น„๊ณ 
insert(pair)O(log n)์œ„์น˜ ์ฐพ๊ธฐ + ํšŒ์ „
insert(hint, pair)amortized O(1)hint ๊ฐ€ ์ •ํ™•ํ•˜๋ฉด
erase(key)O(log n)๋…ธ๋“œ ์ฐพ๊ธฐ + ๋ณต๊ตฌ
erase(iterator)amortized O(1)iterator ์ง์ ‘ ๊ฐ€์ง
find(key)O(log n)ํ‘œ์ค€ BST ๊ฒ€์ƒ‰
count(key)O(log n)map ์€ 0/1, multimap ์€ ๋™์ผ ํ‚ค ๊ฐœ์ˆ˜
contains(key) (C++20)O(log n)find != end ์™€ ๋™์ผ
operator[](key)O(log n)์—†์œผ๋ฉด default ์‚ฝ์ž… (mutating!)
at(key)O(log n)์—†์œผ๋ฉด std::out_of_range ์˜ˆ์™ธ
lower_bound(key)O(log n)key ์ด์ƒ์˜ ์ฒซ ์›์†Œ
upper_bound(key)O(log n)key ์ดˆ๊ณผ์˜ ์ฒซ ์›์†Œ
equal_range(key)O(log n)[lower, upper) ์Œ
begin() / end()O(1)๋ณดํ†ต ์บ์‹œ๋œ ํฌ์ธํ„ฐ
size()O(1)๋ณ„๋„ ์นด์šดํ„ฐ ์œ ์ง€
์ „์ฒด ์ˆœํšŒO(n)์ค‘์œ„ ์ˆœํšŒ โ†’ ์ •๋ ฌ๋œ ํ‚ค ์ˆœ์„œ

4-2. operator[] ์˜ ํ•จ์ •

1
2
3
4
std::map<std::string, int> m;
m["Alice"] = 30;        // ์‚ฝ์ž…
int x = m["Bob"];       // โ˜… Bob ์ด ์—†์œผ๋ฉด default(0) ๋กœ ์‚ฝ์ž…๋จ!
                        //    ๊ทธ๋ฆฌ๊ณ  x ๋Š” 0
1
2
3
4
5
// const map ์—์„œ๋Š” ์ปดํŒŒ์ผ ์—๋Ÿฌ
const std::map<std::string, int> cm = {{"Alice", 30}};
int x = cm["Alice"];    // โŒ ์ปดํŒŒ์ผ ์—๋Ÿฌ โ€” operator[] ๊ฐ€ mutating
                        //    ์—†์œผ๋ฉด ์‚ฝ์ž…์„ ํ•ด์•ผ ํ•˜๋ฏ€๋กœ const ์— ๋ชป ์”€
int y = cm.at("Alice"); // โœ… at ์‚ฌ์šฉ

์•ˆ์ „ํ•œ ๋Œ€์•ˆ

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
// 1) find ์‚ฌ์šฉ โ€” ๊ฐ€์žฅ ๋ช…ํ™•
auto it = m.find("Bob");
if (it != m.end())
    std::cout << it->second;

// 2) at โ€” ์—†์œผ๋ฉด ์˜ˆ์™ธ
try {
    int x = m.at("Bob");
} catch (const std::out_of_range&) {
    // ํ‚ค ์—†์Œ
}

// 3) contains (C++20)
if (m.contains("Bob"))
    std::cout << m["Bob"];

// 4) count != 0
if (m.count("Bob"))
    std::cout << m["Bob"];

4-3. ๋ฒ”์œ„ ์กฐํšŒ โ€” map ์˜ ์ •์งํ•œ ๊ฐ•์ 

ํ•ด์‹œ๋งต์œผ๋กœ๋Š” ๋ชป ํ•˜๋Š” ์—ฐ์‚ฐ์ž…๋‹ˆ๋‹ค.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
std::map<int, std::string> events;
events[100] = "A";
events[200] = "B";
events[300] = "C";
events[400] = "D";
events[500] = "E";

// ์‹œ๊ฐ„ 150 ~ 400 ์‚ฌ์ด์˜ ์ด๋ฒคํŠธ
auto from = events.lower_bound(150);   // 200 ๊ฐ€๋ฆฌํ‚ด
auto to   = events.upper_bound(400);   // 500 ๊ฐ€๋ฆฌํ‚ด

for (auto it = from; it != to; ++it)
    std::cout << it->first << ": " << it->second << "\n";
// 200: B
// 300: C
// 400: D

ํ•ด์‹œ๋งต์€ ํ‚ค๊ฐ€ ์ •๋ ฌ๋ผ ์žˆ์ง€ ์•Š์•„ ์ด๋Ÿฐ ๋ฒ”์œ„ ์กฐํšŒ๋ฅผ O(log n) ์œผ๋กœ ๋ชป ํ•จ. ์ด๊ฒŒ ์ •๋ ฌยท๋ฒ”์œ„ ์กฐํšŒ๊ฐ€ ํ•„์š”ํ•  ๋•Œ map ์„ ์„ ํƒํ•˜๋Š” ๊ฒฐ์ •์  ์ด์œ ์ž…๋‹ˆ๋‹ค.

4-4. hint ๋ฅผ ํ™œ์šฉํ•œ amortized O(1) ์‚ฝ์ž…

1
2
3
4
5
6
7
8
std::map<int, int> m;
auto hint = m.end();

// ์ •๋ ฌ๋œ ๋ฐ์ดํ„ฐ๋ฅผ ์ˆœ์„œ๋Œ€๋กœ ์‚ฝ์ž…ํ•  ๋•Œ
for (int i = 0; i < 1'000'000; ++i)
    hint = m.insert(hint, {i, i * 10});  // amortized O(1)

// hint ์—†์ด๋Š” ๋งค๋ฒˆ O(log n) โ†’ ์ด O(n log n)

C++11 ์ดํ›„ hint ๊ฐ€ ์ •ํ™•(์ง์ „ ์œ„์น˜) ํ•˜๋ฉด O(1) ์œผ๋กœ ์ฒ˜๋ฆฌ๋ฉ๋‹ˆ๋‹ค. ์ •๋ ฌ๋œ ์ž…๋ ฅ์— ๋งค์šฐ ํšจ๊ณผ์ .

4-5. ์ˆœํšŒ โ€” ์ค‘์œ„ ์ˆœํšŒ = ์ •๋ ฌ๋œ ์ˆœ์„œ

1
2
3
4
5
6
7
8
9
std::map<int, std::string> m = {
    {3, "three"}, {1, "one"}, {2, "two"}
};

for (const auto& [k, v] : m)
    std::cout << k << ": " << v << "\n";
// 1: one
// 2: two
// 3: three   โ† ์ž๋™ ์ •๋ ฌ

๋‚ด๋ถ€์ ์œผ๋กœ RB-Tree ์˜ ์ค‘์œ„ ์ˆœํšŒ(in-order traversal) โ€” ์™ผ์ชฝ ๋ถ€๋ถ„ํŠธ๋ฆฌ โ†’ ์ž๊ธฐ โ†’ ์˜ค๋ฅธ์ชฝ ๋ถ€๋ถ„ํŠธ๋ฆฌ. ์ด๊ฒŒ BST ์ •์˜์— ์˜ํ•ด ์ •๋ ฌ๋œ ํ‚ค ์ˆœ์„œ๋ฅผ ๋ณด์žฅํ•ฉ๋‹ˆ๋‹ค.


5. iterator ๋ฌดํšจํ™” ๊ทœ์น™ (vectorยทlist ์™€ ๋น„๊ต)

ํ•ต์‹ฌ ํ•œ ๋ฌธ์žฅ

std::map ์˜ iterator ๋Š” ๋…ธ๋“œ ์•ˆ์ •์„ฑ ์ด ๊ฐ•ํ•ด์„œ ์‚ฝ์ž…์€ ๋ฌดํšจํ™”๊ฐ€ ์ „ํ˜€ ์—†๊ณ  ์‚ญ์ œ๋„ ์‚ญ์ œ๋œ ๋…ธ๋“œ๋งŒ ๋ฌดํšจํ™”๋ฉ๋‹ˆ๋‹ค โ€” vector ์™€ ์ •๋ฐ˜๋Œ€, list ์™€ ๋™์ผํ•ฉ๋‹ˆ๋‹ค.

5-1. map ์˜ ๋ฌดํšจํ™” ๊ทœ์น™

์—ฐ์‚ฐiterator ๋ฌดํšจํ™”
insert์—†์Œ โ˜…
emplace์—†์Œ โ˜…
erase(it)์‚ญ์ œ๋œ it ๋งŒ ๋ฌดํšจ
erase(key)ํ•ด๋‹น ๋…ธ๋“œ it ๋งŒ ๋ฌดํšจ
clear()๋ชจ๋‘
1
2
3
4
5
6
7
8
9
10
11
12
std::map<int, std::string> m = {{1, "one"}, {2, "two"}, {3, "three"}};
auto it = m.find(2);                    // it โ†’ (2, "two")

m.insert({4, "four"});                  // โœ… it ๊ทธ๋Œ€๋กœ ์œ ํšจ
m.insert({0, "zero"});                  // โœ… it ๊ทธ๋Œ€๋กœ ์œ ํšจ
m.emplace(5, "five");                   // โœ… it ๊ทธ๋Œ€๋กœ ์œ ํšจ

m.erase(1);                             // โœ… it ์œ ํšจ (๋‹ค๋ฅธ ๋…ธ๋“œ ์‚ญ์ œ)
m.erase(it);                            // โŒ it ๋ฌดํšจํ™” โ€” ์‚ญ์ œ๋œ ๋ณธ์ธ

// erase ํ›„ ๋‹ค์Œ ๋…ธ๋“œ๋ฅผ ์•ˆ์ „ํ•˜๊ฒŒ ์–ป์œผ๋ ค๋ฉด:
auto next_it = m.erase(it);             // C++11+ โ€” ๋‹ค์Œ ๋…ธ๋“œ ๋ฐ˜ํ™˜

์ด๋Š” ๋…ธ๋“œ ๋‹จ์œ„ ์ž๋ฃŒ๊ตฌ์กฐ(list, map, set ๋“ฑ) ์˜ ๊ณตํ†ต ํŠน์„ฑ โ€” RB ํŠธ๋ฆฌ๊ฐ€ ๋…ธ๋“œ๋ฅผ ํž™์— ๋ถ„์‚ฐ ํ• ๋‹นํ•ด ํ•œ ๋…ธ๋“œ ์ด๋™/์‚ญ์ œ๊ฐ€ ๋‹ค๋ฅธ ๋…ธ๋“œ ์ฃผ์†Œ์— ์˜ํ–ฅ ์—†์Šต๋‹ˆ๋‹ค.

5-2. ์ปจํ…Œ์ด๋„ˆ๋ณ„ ๋น„๊ตํ‘œ

ย vectorlistmapunordered_map
๋ฉ”๋ชจ๋ฆฌ ๋ ˆ์ด์•„์›ƒ์—ฐ์†๋ถ„์‚ฐ ๋…ธ๋“œ๋ถ„์‚ฐ ๋…ธ๋“œ (ํŠธ๋ฆฌ)๋ฒ„ํ‚ท ๋ฐฐ์—ด + ๋ถ„์‚ฐ ๋…ธ๋“œ
insert iterator ๋ฌดํšจํ™”์žฌํ• ๋‹น ์‹œ ๋ชจ๋‘์—†์Œ์—†์Œrehash ์‹œ ๋ชจ๋‘
erase iterator ๋ฌดํšจํ™”์œ„์น˜ ์ดํ›„ ๋ชจ๋‘์‚ญ์ œ ๋…ธ๋“œ๋งŒ์‚ญ์ œ ๋…ธ๋“œ๋งŒ์‚ญ์ œ ๋…ธ๋“œ๋งŒ
๋…ธ๋“œ ์•ˆ์ •์„ฑ์•ฝํ•จ๊ฐ•ํ•จ๊ฐ•ํ•จ์•ฝํ•จ (rehash)
์บ์‹œ ์นœํ™”โ˜…โ˜…โ˜…โ˜…โ˜…โ˜…โ˜…โ˜…โ˜…โ˜…
๊ฒ€์ƒ‰ ๋ณต์žก๋„O(n)O(n)O(log n)ํ‰๊ท  O(1)
์ •๋ ฌ์‚ฌ์šฉ์ž ์ฑ…์ž„์‚ฌ์šฉ์ž ์ฑ…์ž„์ž๋™ โ˜…์—†์Œ

map ์˜ iterator ์•ˆ์ •์„ฑ์€ ์™ธ๋ถ€ ์ž๋ฃŒ๊ตฌ์กฐ์— iterator ๋ฅผ ์ €์žฅํ•ด ๋‘˜ ์ˆ˜ ์žˆ๋Š” ๊ฐ•์ ์œผ๋กœ ์ด์–ด์ง‘๋‹ˆ๋‹ค. 13๋ฒˆ list ์˜ ์ •์งํ•œ ์žฅ์ ๊ณผ ๋™์ผํ•œ ๋งฅ๋ฝ.

5-3. unordered_map ์˜ rehash ๋ฌดํšจํ™” โ€” ์ฃผ์˜

1
2
3
4
5
6
7
std::unordered_map<int, int> u;
auto it = u.insert({1, 100}).first;    // it ๊ฐ€ (1, 100) ๊ฐ€๋ฆฌํ‚ด

for (int i = 0; i < 10000; ++i)
    u.insert({i, i});                   // โ˜… rehash ๋ฐœ์ƒ โ†’ ๋ชจ๋“  iterator ๋ฌดํšจ!

*it;                                    // โŒ UB โ€” ๋Œ•๊ธ€๋ง (10๋ฒˆ ํšŒ๊ท€)

ํ•ด์‹œ๋งต์€ ๋กœ๋“œ ํŒฉํ„ฐ ์ดˆ๊ณผ ์‹œ ๋ฒ„ํ‚ท ๋ฐฐ์—ด ํ™•์žฅ + ๋ชจ๋“  ์›์†Œ ์žฌ๋ฐฐ์น˜(rehash) ๊ฐ€ ์ผ์–ด๋‚˜ ๋ชจ๋“  iteratorยทํฌ์ธํ„ฐยท์ฐธ์กฐ๊ฐ€ ๋ฌดํšจํ™”๋ฉ๋‹ˆ๋‹ค. 13๋ฒˆ vector ์žฌํ• ๋‹น๊ณผ ๊ฐ™์€ ํŒจํ„ด.

โ†’ map ์€ ์ด๋Ÿฐ ๋ฌดํšจํ™”๊ฐ€ ์—†์Œ ์ด ์•ˆ์ •์„ฑ ๋ฉด์—์„œ์˜ ๊ฒฐ์ •์  ์ฐจ์ด.


6. ์œ ์‚ฌํ•œ ๋ฒ”์œ„์˜ ๋‹ค๋ฅธ ์ปจํ…Œ์ด๋„ˆ โ€” set / multimap / unordered_*

ํ•ต์‹ฌ ํ•œ ๋ฌธ์žฅ

map ๊ฐ€์กฑ์€ (์ •๋ ฌ vs ํ•ด์‹œ) ร— (ํ‚ค๋งŒ vs ํ‚ค-๊ฐ’) ร— (์ค‘๋ณต ํ—ˆ์šฉ vs ๋ถˆํ—ˆ) ์˜ 8๊ฐ€์ง€ ์กฐํ•ฉ์ž…๋‹ˆ๋‹ค. ๊ฐ€์žฅ ์ž์ฃผ ์“ฐ๋Š” 4๊ฐ€์ง€๋ฅผ ๋จผ์ € ์ตํžˆ๊ณ , ๋‚˜๋จธ์ง€๋Š” ํ‘œ๋กœ ๊ธฐ์–ตํ•˜์„ธ์š”.

6-1. std::set โ€” ํ‚ค๋งŒ ์ €์žฅ

1
2
3
4
5
6
7
8
9
#include <set>

std::set<int> s = {3, 1, 4, 1, 5, 9, 2, 6};
// ์ž๋™ ์ •๋ ฌ + ์ค‘๋ณต ์ œ๊ฑฐ โ†’ {1, 2, 3, 4, 5, 6, 9}

s.insert(7);
s.erase(4);
if (s.count(3))         // ์ •๋ ฌ ์ปจํ…Œ์ด๋„ˆ์˜ ๋ฉค๋ฒ„์‹ญ ๊ฒ€์‚ฌ
    std::cout << "3 exists\n";
  • map ์˜ value ์ œ๊ฑฐ ๋ฒ„์ „, ๋™์ผํ•˜๊ฒŒ RB-Tree ๊ธฐ๋ฐ˜
  • O(log n) insert/find/erase
  • ํ‚ค ์ค‘๋ณต ๋ถˆ๊ฐ€, ์ž๋™ ์ •๋ ฌ

6-2. std::multimap โ€” ์ค‘๋ณต ํ‚ค ํ—ˆ์šฉ

1
2
3
4
5
6
7
8
9
10
11
12
#include <map>

std::multimap<std::string, int> scores;
scores.insert({"Alice", 85});
scores.insert({"Alice", 92});      // โœ… ๊ฐ™์€ ํ‚ค๋กœ ๋‘ ๋ฒˆ์งธ ํ•ญ๋ชฉ
scores.insert({"Alice", 78});
scores.insert({"Bob",   90});

// Alice ์˜ ๋ชจ๋“  ์ ์ˆ˜ ์กฐํšŒ โ€” equal_range ์‚ฌ์šฉ
auto [from, to] = scores.equal_range("Alice");
for (auto it = from; it != to; ++it)
    std::cout << it->second << "\n";   // 85, 92, 78
  • ๊ฐ™์€ ํ‚ค์— ์—ฌ๋Ÿฌ ๊ฐ’ ์ €์žฅ ๊ฐ€๋Šฅ
  • operator[] ์™€ at ์€ ์—†์Œ (์–ด๋–ค ๊ฐ’์„ ๋ฐ˜ํ™˜ํ• ์ง€ ๋ชจํ˜ธ)
  • equal_range ๋กœ ๊ฐ™์€ ํ‚ค ๋ฒ”์œ„ ์กฐํšŒ
  • ์‚ฌ์šฉ ์‚ฌ๋ก€: ์‹œ๊ฐ„ โ†’ ์ด๋ฒคํŠธ (๊ฐ™์€ ์‹œ๊ฐ„์— ์—ฌ๋Ÿฌ ์ด๋ฒคํŠธ), ํƒœ๊ทธ โ†’ ํ•ญ๋ชฉ

6-3. std::multiset

1
2
3
std::multiset<int> ms = {1, 2, 2, 3, 3, 3};
// ์ž๋™ ์ •๋ ฌ, ์ค‘๋ณต ํ—ˆ์šฉ โ†’ {1, 2, 2, 3, 3, 3}
ms.count(3);   // 3 (์ค‘๋ณต ๊ฐœ์ˆ˜ ๋ฐ˜ํ™˜ โ€” set ๊ณผ ๋‹ค๋ฅธ ์ )

6-4. std::unordered_map โ€” ํ•ด์‹œ ๊ธฐ๋ฐ˜

1
2
3
4
5
6
7
8
9
10
11
12
13
14
#include <unordered_map>

std::unordered_map<std::string, int> u;
u["Alice"] = 30;
u["Bob"]   = 25;

// ํ‰๊ท  O(1) ์กฐํšŒ
if (u.contains("Alice"))    // C++20
    std::cout << u["Alice"];

// ๋ฒ„ํ‚ท ํ†ต๊ณ„
std::cout << "size: " << u.size() << "\n";
std::cout << "bucket count: " << u.bucket_count() << "\n";
std::cout << "load factor: " << u.load_factor() << "\n";  // size / bucket_count

๋‚ด๋ถ€ ๊ตฌ์กฐ

1
2
3
4
5
6
7
8
9
10
๋ฒ„ํ‚ท ๋ฐฐ์—ด + ์ฒด์ด๋‹ (Separate Chaining)

    bucket[0]  โ†’  null
    bucket[1]  โ†’  ("Alice", 30) โ†’ null
    bucket[2]  โ†’  null
    bucket[3]  โ†’  ("Bob", 25) โ†’ ("Carol", 35) โ†’ null   โ† ์ถฉ๋Œ
    bucket[4]  โ†’  null
    ...

ํ•ด์‹œ ํ•จ์ˆ˜: hash(key) % bucket_count โ†’ ๋ฒ„ํ‚ท ์ธ๋ฑ์Šค
  • ํ‰๊ท  O(1) (๊ท ๋“ฑํ•œ ํ•ด์‹œ ๋ถ„ํฌ + ์ ์ ˆํ•œ ๋กœ๋“œ ํŒฉํ„ฐ)
  • ์ตœ์•… O(n) (๋ชจ๋“  ํ‚ค๊ฐ€ ํ•œ ๋ฒ„ํ‚ท์— ๋ชฐ๋ฆด ๊ฒฝ์šฐ)
  • ์ •๋ ฌ ์—†์Œ, ๋ฉ”๋ชจ๋ฆฌ ๋” ์‚ฌ์šฉ

6-5. unordered_set / unordered_multimap / unordered_multiset

1
2
3
std::unordered_set<int> us = {3, 1, 4, 1, 5};            // ํ•ด์‹œ + ํ‚ค๋งŒ + ์ค‘๋ณต X
std::unordered_multimap<std::string, int> umm;            // ํ•ด์‹œ + ํ‚ค-๊ฐ’ + ์ค‘๋ณต O
std::unordered_multiset<int> ums = {1, 2, 2, 3};          // ํ•ด์‹œ + ํ‚ค๋งŒ + ์ค‘๋ณต O

ํŠน์ง•์€ ์ •๋ ฌ ์ปจํ…Œ์ด๋„ˆ(set, multimap, multiset) ์˜ ํ•ด์‹œ ๋ฒ„์ „๊ณผ ๋™์ผ.

6-6. 8๊ฐ€์ง€ ์กฐํ•ฉ ์ข…ํ•ฉํ‘œ

ย ์ •๋ ฌ (RB-Tree)ํ•ด์‹œ (Hash Table)
ํ‚ค-๊ฐ’ + ์ค‘๋ณต Xstd::mapstd::unordered_map
ํ‚ค-๊ฐ’ + ์ค‘๋ณต Ostd::multimapstd::unordered_multimap
ํ‚ค๋งŒ + ์ค‘๋ณต Xstd::setstd::unordered_set
ํ‚ค๋งŒ + ์ค‘๋ณต Ostd::multisetstd::unordered_multiset

6-7. ์„ ํƒ ๊ฐ€์ด๋“œ

์š”๊ตฌ์‚ฌํ•ญ์„ ํƒ
ํ‚ค ์ •๋ ฌ ํ•„์š”map / set
๋น ๋ฅธ ์กฐํšŒ (์ˆœ์„œ ๋ฌด๊ด€)unordered_map / unordered_set
ํ‚ค ์ค‘๋ณต ํ—ˆ์šฉ + ์ •๋ ฌmultimap / multiset
ํ‚ค ์ค‘๋ณต ํ—ˆ์šฉ + ๋น ๋ฅธ ์กฐํšŒunordered_multimap / unordered_multiset
๋ฒ”์œ„ ์กฐํšŒ (lower/upper_bound)map / set โ˜… ํ•ด์‹œ ๋ถˆ๊ฐ€
์ตœ์•… ์‹œ๊ฐ„ ๋ณด์žฅ ํ•„์š”map / set (ํ•ด์‹œ๋Š” O(n) ์ตœ์•…)
ํ‚ค๊ฐ€ ํ•ด์‹œ ํ•จ์ˆ˜ ์ •์˜ ์–ด๋ ค์›€map / set (Compare ๋งŒ ์ •์˜)

6-8. map vs unordered_map ์ •๋Ÿ‰ ๋น„๊ต

ํ•ญ๋ชฉstd::mapstd::unordered_map
์ž๋ฃŒ๊ตฌ์กฐRed-Black Treeํ•ด์‹œ ํ…Œ์ด๋ธ” (์ฒด์ด๋‹)
ํ‰๊ท  ์กฐํšŒO(log n)O(1)
์ตœ์•… ์กฐํšŒO(log n)O(n)
์ •๋ ฌ์ž๋™์—†์Œ
๋ฒ”์œ„ ์กฐํšŒO(log n)์ง€์› ์•ˆ ํ•จ
iterator ์•ˆ์ •์„ฑ์‚ฝ์ž… ๋ฌดํšจํ™” ์—†์Œrehash ์‹œ ๋ชจ๋‘ ๋ฌดํšจ
๋ฉ”๋ชจ๋ฆฌ ์˜ค๋ฒ„ํ—ค๋“œ๋…ธ๋“œ๋‹น ~60B (8B ํ‚ค-๊ฐ’ ๊ธฐ์ค€)๋ฒ„ํ‚ท + ๋…ธ๋“œ
์บ์‹œ ์นœํ™”์„ฑ๋‚ฎ์Œ (ํŠธ๋ฆฌ ๋…ธ๋“œ ๋ถ„์‚ฐ)๋ณดํ†ต (๋ฒ„ํ‚ท ๋ฐฐ์—ด์€ ์—ฐ์†)
ํ‚ค ์š”๊ตฌ์‚ฌํ•ญCompare (์ •๋ ฌ ๊ฐ€๋Šฅ)Hash + equal_to (ํ•ด์‹œ + ๋น„๊ต)
์‚ฌ์šฉ ์˜ˆ์ •๋ ฌ ์‚ฌ์ „, ์‹œ๊ฐ„์ˆœ ์ด๋ฒคํŠธ์ธ๋ฉ”๋ชจ๋ฆฌ ์บ์‹œ, ๋น ๋ฅธ ๋ฃฉ์—…

7. ์ฝ”๋“œ ์˜ˆ์ œ โ€” ๊ธฐ๋ณธ ์‚ฌ์šฉ / Custom Compare / emplace

7-1. ๊ธฐ๋ณธ ์‚ฌ์šฉ๋ฒ•

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
#include <map>
#include <iostream>
#include <string>

int main() {
    std::map<std::string, int> ages;

    // ์‚ฝ์ž… โ€” 4๊ฐ€์ง€ ๋ฐฉ๋ฒ•
    ages["Alice"] = 30;                          // operator[]
    ages.insert({"Bob", 25});                    // insert
    ages.insert(std::make_pair("Carol", 35));
    ages.emplace("Dave", 40);                    // emplace (in-place)

    // ์กฐํšŒ
    if (auto it = ages.find("Alice"); it != ages.end())
        std::cout << it->first << ": " << it->second << "\n";

    // ์•ˆ์ „ ์ ‘๊ทผ
    try {
        int age = ages.at("Eve");                // ์—†์œผ๋ฉด ์˜ˆ์™ธ
    } catch (const std::out_of_range& e) {
        std::cout << "not found\n";
    }

    // ์‚ญ์ œ
    ages.erase("Bob");

    // ์ˆœํšŒ (์ •๋ ฌ ์ˆœ์„œ)
    for (const auto& [name, age] : ages)
        std::cout << name << ": " << age << "\n";

    // ํฌ๊ธฐ/๋นˆ ์—ฌ๋ถ€
    std::cout << "size: " << ages.size() << "\n";
    std::cout << "empty: " << ages.empty() << "\n";
}

7-2. Custom Compare โ€” ์ •๋ ฌ ๊ธฐ์ค€ ๋ณ€๊ฒฝ

1
2
3
4
5
6
7
8
9
10
11
// ๋‚ด๋ฆผ์ฐจ์ˆœ ์ •๋ ฌ โ€” std::greater ์‚ฌ์šฉ
std::map<int, std::string, std::greater<int>> desc;
desc[1] = "one";
desc[3] = "three";
desc[2] = "two";

for (const auto& [k, v] : desc)
    std::cout << k << ": " << v << "\n";
// 3: three
// 2: two
// 1: one
1
2
3
4
5
6
7
8
9
10
11
12
13
// ๋žŒ๋‹ค๋กœ ์ปค์Šคํ…€ ๋น„๊ต (๋Œ€์†Œ๋ฌธ์ž ๋ฌด์‹œ ์ •๋ ฌ)
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);
m["Alice"] = 1;
m["bob"]   = 2;
m["CAROL"] = 3;
// ์ •๋ ฌ ์‹œ ๋Œ€์†Œ๋ฌธ์ž ๋ฌด์‹œ: alice โ†’ bob โ†’ CAROL

7-3. structured binding (C++17)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
std::map<std::string, int> m = {{"Alice", 30}, {"Bob", 25}};

// C++17 ์ด์ „
for (auto it = m.begin(); it != m.end(); ++it)
    std::cout << it->first << ": " << it->second << "\n";

// C++17 ์ดํ›„ โ€” ํ›จ์”ฌ ๊ฐ„๊ฒฐ
for (const auto& [name, age] : m)
    std::cout << name << ": " << age << "\n";

// insert ๊ฒฐ๊ณผ ๋ถ„ํ•ด
auto [it, inserted] = m.insert({"Carol", 35});
if (inserted)
    std::cout << "newly inserted\n";

7-4. emplace vs insert vs operator[]

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
std::map<std::string, std::vector<int>> m;

// 1) operator[] โ€” default ์ƒ์„ฑ ํ›„ ๋Œ€์ž… (2๋‹จ๊ณ„, ๋น„ํšจ์œจ์ ์ผ ์ˆ˜ ์žˆ์Œ)
m["A"] = std::vector<int>{1, 2, 3};
//   โ†‘ 1) m["A"] ๊ฐ€ default vector ์‚ฝ์ž…
//     2) ๊ทธ ์ž๋ฆฌ์— ์ƒˆ vector ๋Œ€์ž… (์ด๋™)

// 2) insert โ€” ์ž„์‹œ pair ์ƒ์„ฑ
m.insert({"B", std::vector<int>{4, 5, 6}});
//   โ†‘ pair ์ž„์‹œ ๊ฐ์ฒด ์ƒ์„ฑ + vector ๋ณต์‚ฌยท์ด๋™

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

// 4) try_emplace (C++17) โ€” ํ‚ค ์žˆ์œผ๋ฉด ์•„๋ฌด ์ผ๋„ ์•ˆ ํ•จ
auto [it, inserted] = m.try_emplace("A", std::vector<int>{99, 99});
// "A" ์ด๋ฏธ ์กด์žฌ โ†’ vector ์ธ์ž์กฐ์ฐจ ๋งŒ๋“ค์ง€ ์•Š์Œ
// inserted == false, it ๋Š” ๊ธฐ์กด ("A", {1,2,3}) ๊ฐ€๋ฆฌํ‚ด

// 5) insert_or_assign (C++17) โ€” ์žˆ์œผ๋ฉด ๋Œ€์ž…, ์—†์œผ๋ฉด ์‚ฝ์ž…
m.insert_or_assign("D", std::vector<int>{10, 11});
// ์˜๋„๊ฐ€ ๋ช…ํ™• โ€” operator[] ์˜ default ์‚ฝ์ž… ํŠธ๋žฉ ํšŒํ”ผ

7-5. try_emplace ์˜ ์ง„์งœ ๊ฐ€์น˜

1
2
3
4
5
6
7
8
9
10
11
12
// operator[] ํ•จ์ •
std::map<std::string, std::unique_ptr<Resource>> resources;

resources["key1"] = std::make_unique<Resource>("data1");
// ๋งŒ์•ฝ "key1" ์ด ์ด๋ฏธ ์žˆ์œผ๋ฉด? โ†’ ๊ธฐ์กด unique_ptr ํŒŒ๊ดด + ์ƒˆ unique_ptr ๋Œ€์ž…
// ์˜๋„๊ฐ€ "์žˆ์œผ๋ฉด ๊ทธ๋Œ€๋กœ ๋‘๊ณ  ์—†์„ ๋•Œ๋งŒ ๋งŒ๋“ค๊ธฐ" ๋ผ๋ฉด ๋ฒ„๊ทธ!

// try_emplace ๋กœ ์˜๋„ ๋ช…ํ™•ํ™”
auto [it, inserted] = resources.try_emplace("key1", std::make_unique<Resource>("data1"));
if (!inserted) {
    // ์ด๋ฏธ ์กด์žฌ โ†’ make_unique ๋„ ํ˜ธ์ถœ๋˜์ง€ ์•Š์Œ โ˜…
}

C++17 ์˜ try_emplace ๋Š” ์ž„์‹œ ์ธ์ž ์ƒ์„ฑ ์ž์ฒด๋ฅผ ํšŒํ”ผํ•ด ๋ฌด๋ธŒ-์˜จ๋ฆฌ ํƒ€์ž…(unique_ptr) ์—์„œ ํŠนํžˆ ์œ ์šฉํ•ฉ๋‹ˆ๋‹ค.

7-6. ํ‚ค ๊ฐ์ฒด์— < ์ •์˜ํ•˜๊ธฐ

1
2
3
4
5
6
7
8
9
10
11
12
struct Point {
    int x, y;
    bool operator<(const Point& other) const {
        return std::tie(x, y) < std::tie(other.x, other.y);
    }
};

std::map<Point, std::string> places;
places[{1, 2}] = "A";
places[{3, 1}] = "B";
places[{1, 5}] = "C";
// ์ •๋ ฌ: (1,2) โ†’ (1,5) โ†’ (3,1)

ํ•ด์‹œ๋งต์€ ํ‚ค์— std::hash ํŠน์ˆ˜ํ™” + operator== ๊ฐ€ ํ•„์š”ํ•˜์ง€๋งŒ, ํŠธ๋ฆฌ๋งต์€ operator< ๋งŒ ์žˆ์œผ๋ฉด ๋ฉ๋‹ˆ๋‹ค โ€” ์ด๊ฒŒ ์ •๋ ฌ ์ปจํ…Œ์ด๋„ˆ์˜ ์ž‘์€ ํŽธ์˜์„ฑ.


8. ๋ฉด์ ‘ ๋‹จ๊ณจ ๊ผฌ๋ฆฌ๋ฌผ๊ธฐ

8-1. map vs unordered_map ์–ธ์ œ ์–ด๋–ค ๊ฑธ?

1
2
3
4
5
6
7
8
9
10
11
map ์„ ํƒ:
  - ํ‚ค ์ •๋ ฌ์ด ๊ฒฐ๊ณผ์ ์œผ๋กœ ํ•„์š” (์ •๋ ฌ ์ถœ๋ ฅ, ๋ฒ”์œ„ ์กฐํšŒ)
  - ์ตœ์•… ์‹œ๊ฐ„ ๋ณด์žฅ์ด ํ•„์š” (์‹ค์‹œ๊ฐ„ ์‹œ์Šคํ…œ, SLA)
  - ํ‚ค์— ํ•ด์‹œ ํ•จ์ˆ˜ ์ •์˜๊ฐ€ ์–ด๋ ค์›€ (๋ณต์žกํ•œ ์‚ฌ์šฉ์ž ์ •์˜ ํƒ€์ž…)
  - ๋ฉ”๋ชจ๋ฆฌ ํšจ์œจ๋ณด๋‹ค ์•ˆ์ •์„ฑ ์šฐ์„ 

unordered_map ์„ ํƒ:
  - ์ˆœ์„œ ๋ฌด๊ด€ (์ธ๋ฉ”๋ชจ๋ฆฌ ์บ์‹œ, ๋ฃฉ์—… ํ…Œ์ด๋ธ”)
  - ํ‰๊ท  ์ฒ˜๋ฆฌ๋Ÿ‰ ์ตœ๋Œ€ํ™” (๊ฒŒ์ž„ ์—”์ง„, DB ์ธ๋ฑ์Šค)
  - ํ‚ค๊ฐ€ ํ•ด์‹œ ํ•จ์ˆ˜์— ์ž˜ ๋ถ„ํฌ (์ •์ˆ˜, ๋ฌธ์ž์—ด, ID)
  - rehash ๋ฌดํšจํ™”๋ฅผ ์‹ ๊ฒฝ ์•ˆ ์จ๋„ ๋˜๋Š” ์›Œํฌ๋กœ๋“œ

8-2. RB-Tree ํšŒ์ „์€ ๋ช‡ ์ข…๋ฅ˜?

1
2
3
4
5
6
7
8
4๊ฐ€์ง€ ์ผ€์ด์Šค (LL, LR, RL, RR) โ”€ ํšŒ์ „ ์ž์ฒด๋Š” 2์ข…๋ฅ˜:
  - Right Rotation (์˜ค๋ฅธ์ชฝ ํšŒ์ „) : LL ์ผ€์ด์Šค์—์„œ ์‚ฌ์šฉ
  - Left Rotation (์™ผ์ชฝ ํšŒ์ „)    : RR ์ผ€์ด์Šค์—์„œ ์‚ฌ์šฉ
  - LR : ๋จผ์ € Left โ†’ ๊ทธ ๋‹ค์Œ Right (์ด์ค‘ ํšŒ์ „)
  - RL : ๋จผ์ € Right โ†’ ๊ทธ ๋‹ค์Œ Left (์ด์ค‘ ํšŒ์ „)

์‚ฝ์ž… ๋ณต๊ตฌ ์‹œ ํšŒ์ „ ํšŸ์ˆ˜: ์ตœ๋Œ€ 2ํšŒ
์‚ญ์ œ ๋ณต๊ตฌ ์‹œ ํšŒ์ „ ํšŸ์ˆ˜: ์ตœ๋Œ€ 3ํšŒ

8-3. ๋ฉ”๋ชจ๋ฆฌ ์˜ค๋ฒ„ํ—ค๋“œ โ€” map ๋…ธ๋“œ๋Š” ์–ผ๋งˆ๋‚˜ ํฐ๊ฐ€?

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
// libstdc++ ๊ธฐ์ค€ ๋…ธ๋“œ ๋ฉ”๋ชจ๋ฆฌ (x86_64):
//   color  4~8B (์ •๋ ฌ ํŒจ๋”ฉ ํฌํ•จ)
//   parent 8B
//   left   8B
//   right  8B
//   data   sizeof(pair<const Key, T>)
//   ํž™ ํ—ค๋” ~16B (allocator ๋งˆ๋‹ค ๋‹ค๋ฆ„)

// std::map<int, int>:
//   8 + 8 + 8 + 8 + (4+4+ํŒจ๋”ฉ 4) + 16 โ‰ˆ 60 ๋ฐ”์ดํŠธ
//   ๋ฐ์ดํ„ฐ 8๋ฐ”์ดํŠธ(int ํ‚ค-๊ฐ’) โ†’ ํšจ์œจ ~13%

// std::map<string, string> (๊ฐ string 32B ๊ฐ€์ •):
//   8 + 8 + 8 + 8 + 64 + 16 = 112 ๋ฐ”์ดํŠธ
//   ๋ฐ์ดํ„ฐ 64๋ฐ”์ดํŠธ โ†’ ํšจ์œจ ~57%

13๋ฒˆ์—์„œ ๋ณธ list ์˜ ๋ถ„์„๊ณผ ๋™์ผํ•œ ํŒจํ„ด โ€” ์ž‘์€ ํ‚ค-๊ฐ’์ผ์ˆ˜๋ก ๋…ธ๋“œ ํ—ค๋” ์˜ค๋ฒ„ํ—ค๋“œ๊ฐ€ ๋น„๋Œ€ํ•ฉ๋‹ˆ๋‹ค.

8-4. ์บ์‹œ ์นœํ™”์„ฑ โ€” map ์€ vector ๋ณด๋‹ค ๋А๋ฆฐ๊ฐ€?

1
2
3
4
5
6
7
8
๊ฐ™์€ N๊ฐœ ์ •์ˆ˜ ์ˆœํšŒ:
  std::vector<int>          : ~1 ms  (1M ์›์†Œ)  โ† 13๋ฒˆ
  std::list<int>            : ~100 ms          โ† 13๋ฒˆ
  std::map<int, int>        : ~50 ms ์ •๋„      โ† ํŠธ๋ฆฌ ๋…ธ๋“œ ๋ถ„์‚ฐ
  std::unordered_map<int,int>: ~10 ms ์ •๋„     โ† ๋ฒ„ํ‚ท + ์ฒด์ด๋‹

์ˆœ์„œ:
  vector โ‰ซ unordered_map > map > list

map ์€ ๋…ธ๋“œ๊ฐ€ ํž™์— ๋ถ„์‚ฐ๋˜์ง€๋งŒ ํŠธ๋ฆฌ ๊ตฌ์กฐ๋ผ ๋ถ€๋ถ„์  ์ง€์—ญ์„ฑ(๋ถ€๋ชจ-์ž์‹์ด ๋น„๊ต์  ๊ฐ€๊นŒ์›€) ์ด ์žˆ์–ด list ๋ณด๋‹ค๋Š” ์บ์‹œ ์นœํ™”์ ์ž…๋‹ˆ๋‹ค. ๋‹ค๋งŒ vector ์™€๋Š” ๋น„๊ต ๋ถˆ๊ฐ€.

8-5. operator[] ๊ฐ€ const map ์—์„œ ์•ˆ ๋˜๋Š” ์ด์œ 

1
2
const std::map<int, int> cm = {{1, 100}};
int x = cm[1];           // โŒ ์ปดํŒŒ์ผ ์—๋Ÿฌ

operator[] ์˜ ์‹œ๊ทธ๋‹ˆ์ฒ˜:

1
2
3
4
5
6
T& operator[](const Key& k) {
    auto it = find(k);
    if (it == end())
        return insert({k, T{}}).first->second;   // โ˜… ์—†์œผ๋ฉด default ์‚ฝ์ž… (mutating)
    return it->second;
}

ํ‚ค๊ฐ€ ์—†์„ ๋•Œ ์ž๋™์œผ๋กœ default ๊ฐ’์„ ์‚ฝ์ž…ํ•˜๋ฏ€๋กœ const ๊ฐ์ฒด์—์„œ ํ˜ธ์ถœ ๋ถˆ๊ฐ€. const ์—์„œ๋Š” at(k) ๋˜๋Š” find(k) ๋ฅผ ์จ์•ผ ํ•ฉ๋‹ˆ๋‹ค.

์ด ํ•จ์ •์€ 13๋ฒˆ vector::operator[] (๊ฒฝ๊ณ„ ๊ฒ€์‚ฌ ์•ˆ ํ•จ) ๊ณผ ํ•จ๊ป˜ ๋ฉด์ ‘ ๋‹จ๊ณจ โ€” STL ์˜ โ€œํŽธ์˜ vs ์•ˆ์ „โ€ ํŠธ๋ ˆ์ด๋“œ์˜คํ”„ ์‚ฌ๋ก€.

8-6. ์™œ ๋นจ๊ฐ•ยท๊ฒ€์ • ๋‘ ์ƒ‰๋งŒ? ๋” ๋งŽ์ด ์“ฐ๋ฉด ์•ˆ ๋˜๋‚˜?

๋นจ๊ฐ•ยท๊ฒ€์ • ๋‘ ์ƒ‰๋งŒ์œผ๋กœ๋„ ํŠธ๋ฆฌ ๋†’์ด 2 log(n+1) ๋ณด์žฅ์— ์ถฉ๋ถ„ํ•ฉ๋‹ˆ๋‹ค. ์ƒ‰์„ ๋Š˜๋ ค๋„ ๊ท ํ˜• ๋ณด์žฅ์— ์ถ”๊ฐ€ ์ด๋“์ด ๊ฑฐ์˜ ์—†๊ณ , ๋…ธ๋“œ๋‹น ๋ฉ”๋ชจ๋ฆฌ๋งŒ ๋Š˜์–ด๋‚ฉ๋‹ˆ๋‹ค(์ƒ‰ ์ •๋ณด๊ฐ€ ~1๋น„ํŠธ์—์„œ ๋” ์ปค์ง).

8-7. ์ƒˆ ๋…ธ๋“œ๋Š” ์™œ ๋นจ๊ฐ•์œผ๋กœ ์‚ฝ์ž…ํ•˜๋‚˜?

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

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

๋”ฐ๋ผ์„œ ์ƒˆ ๋…ธ๋“œ๋Š” ํ•ญ์ƒ ๋นจ๊ฐ• โ€” ๋ณต๊ตฌ ๋น„์šฉ ์ตœ์†Œํ™”์˜ ์˜๋ฆฌํ•œ ํŠธ๋ฆญ.

8-8. AVL ๊ณผ RB ์ค‘ ๋ญ๊ฐ€ ๋” ์ข‹๋‚˜?

1
2
3
4
5
6
7
์›Œํฌ๋กœ๋“œ ๋ถ„์„:
  ๊ฒ€์ƒ‰ ์œ„์ฃผ (์กฐํšŒ โ‰ซ ์‚ฝ์ž…/์‚ญ์ œ) โ†’ AVL โ€” ํŠธ๋ฆฌ ๋†’์ด ์•ฝ๊ฐ„ ๋‚ฎ์Œ
  ๊ฐฑ์‹  ์œ„์ฃผ (์‚ฝ์ž…ยท์‚ญ์ œ ์ž์ฃผ)   โ†’ RB  โ€” ํšŒ์ „ ํšŸ์ˆ˜ ์ ์Œ
  ๋ฒ”์šฉ (๋‘˜ ๋‹ค ์ž์ฃผ)            โ†’ RB โ€” ํ‘œ์ค€ ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ๋“ค์ด ์ฑ„ํƒ

STL/Linux ์ปค๋„/Java TreeMap ๋ชจ๋‘ RB ์ฑ„ํƒ โ€” ๋ฒ”์šฉ์„ฑ + ํšŒ์ „ ๋น„์šฉ ๊ท ํ˜•์ด ์ข‹์•„์„œ.
DB ์ธ๋ฑ์Šค(B-Tree ๋ณ€ํ˜•) ๊ฐ™์€ ๋””์Šคํฌ ์ž๋ฃŒ๊ตฌ์กฐ๋Š” ๋‹ค๋ฅธ ํŠธ๋ฆฌ ์‚ฌ์šฉ.

8-9. unordered_map ์˜ rehash ๋Š” ์–ธ์ œ ์ผ์–ด๋‚˜๋‚˜?

1
2
3
4
5
6
7
8
9
10
11
์กฐ๊ฑด: load_factor() > max_load_factor()
       (size / bucket_count > 1.0 ๋ณดํ†ต)

rehash ๋™์ž‘:
  1) ์ƒˆ ๋ฒ„ํ‚ท ๋ฐฐ์—ด ํ• ๋‹น (๋ณดํ†ต 2๋ฐฐ ํฌ๊ธฐ, ์†Œ์ˆ˜ ๊ทผ์ฒ˜๋กœ ๋ฐ˜์˜ฌ๋ฆผ)
  2) ๋ชจ๋“  ์›์†Œ๋ฅผ ์ƒˆ ํ•ด์‹œ๊ฐ’์œผ๋กœ ๋‹ค์‹œ ๋ถ„๋ฐฐ
  3) ๊ธฐ์กด ๋ฒ„ํ‚ท ๋ฐฐ์—ด ํ•ด์ œ

๋น„์šฉ: O(n) โ€” 13๋ฒˆ vector ์žฌํ• ๋‹น๊ณผ ๋™์ผํ•œ ํŒจํ„ด

ํšŒํ”ผ: u.reserve(n) ์œผ๋กœ ๋ฏธ๋ฆฌ ๋ฒ„ํ‚ท ํ™•๋ณด โ†’ ํ•œ ๋ฒˆ์— ์ถฉ๋ถ„ํ•œ ํฌ๊ธฐ ํ• ๋‹น

8-10. ํ•ด์‹œ ์ถฉ๋Œ์ด ์‹ฌํ•˜๋ฉด ์–ด๋–ป๊ฒŒ ๋˜๋‚˜?

1
2
3
4
5
6
7
8
9
10
11
// ๋ชจ๋“  ํ‚ค๊ฐ€ ๊ฐ™์€ ํ•ด์‹œ๊ฐ’์„ ๊ฐ€์ง€๋Š” ์•…์˜์  ์ž…๋ ฅ:
struct BadHash {
    size_t operator()(int k) const { return 0; }   // ํ•ญ์ƒ 0 ๋ฐ˜ํ™˜
};

std::unordered_map<int, int, BadHash> u;
for (int i = 0; i < 1000; ++i)
    u.insert({i, i});

// ๋ชจ๋“  ์›์†Œ๊ฐ€ bucket[0] ์— ์ฒด์ธ๋จ โ†’ ์‚ฌ์‹ค์ƒ ์—ฐ๊ฒฐ ๋ฆฌ์ŠคํŠธ
u.find(999);   // O(n) โ€” 1000๋ฒˆ ๋น„๊ต

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

8-11. multimap ์—์„œ ๊ฐ™์€ ํ‚ค ์ˆœ์„œ๋Š” ๋ณด์žฅ๋˜๋‚˜?

C++11 ์ดํ›„๋กœ ์‚ฝ์ž… ์ˆœ์„œ๊ฐ€ ๋ณด์žฅ๋ฉ๋‹ˆ๋‹ค (์•ˆ์ •์„ฑ, stability).

1
2
3
4
5
6
7
8
9
std::multimap<int, std::string> mm;
mm.insert({1, "first"});
mm.insert({1, "second"});
mm.insert({1, "third"});

auto [from, to] = mm.equal_range(1);
for (auto it = from; it != to; ++it)
    std::cout << it->second << " ";
// first second third  โ† ์‚ฝ์ž… ์ˆœ์„œ ๋ณด์žฅ

C++03 ์ด์ „์—” ๋ณด์žฅ ์—†์—ˆ์œผ๋‚˜ C++11 ์ดํ›„ ํ‘œ์ค€ํ™”.


9. ์–ธ๋ฆฌ์–ผ TMap vs STL

ํ•ต์‹ฌ ํ•œ ๋ฌธ์žฅ

์–ธ๋ฆฌ์–ผ์˜ TMap ์€ std::unordered_map ๋Œ€์‘์˜ ํ•ด์‹œ ํ…Œ์ด๋ธ”์ž…๋‹ˆ๋‹ค. STL std::map ์— ์ง์ ‘ ๋Œ€์‘ํ•˜๋Š” RB-Tree ์ปจํ…Œ์ด๋„ˆ๋Š” 1๊ธ‰์œผ๋กœ ๋‘์ง€ ์•Š์•˜๊ณ , ์ •๋ ฌ์ด ํ•„์š”ํ•˜๋ฉด TSortedMap ์„ ์‚ฌ์šฉํ•ฉ๋‹ˆ๋‹ค โ€” ์บ์‹œ ์นœํ™” ์šฐ์„  ์ฒ ํ•™.

9-1. TMap<KeyType, ValueType> โ€” ํ•ด์‹œ ๊ธฐ๋ฐ˜

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
TMap<FString, int32> Ages;

Ages.Add("Alice", 30);              // std::unordered_map::insert ๋Œ€์‘
Ages.Add("Bob", 25);
Ages["Carol"] = 35;                 // operator[] (์—†์œผ๋ฉด default ์‚ฝ์ž…์€ ๋™์ผ)

// ์กฐํšŒ
if (int32* PAge = Ages.Find("Alice"))
    UE_LOG(LogTemp, Log, TEXT("Alice: %d"), *PAge);

// ์‚ญ์ œ
Ages.Remove("Bob");

// ์ˆœํšŒ (ํ•ด์‹œ ์ˆœ์„œ โ€” ์ •๋ ฌ X)
for (const auto& Pair : Ages)
    UE_LOG(LogTemp, Log, TEXT("%s: %d"), *Pair.Key, Pair.Value);

๋‚ด๋ถ€ ๊ตฌ์กฐ:

  • ํ•ด์‹œ ํ…Œ์ด๋ธ” + open addressing ๋ณ€ํ˜• (์ฒด์ด๋‹ ์•„๋‹˜ โ€” ์บ์‹œ ์นœํ™” ์œ„ํ•ด)
  • GetTypeHash(Key) ๋กœ ํ•ด์‹œ ๊ณ„์‚ฐ โ€” ์‚ฌ์šฉ์ž ์ •์˜ ํƒ€์ž…์€ ์ด ํ•จ์ˆ˜ ์˜ค๋ฒ„๋กœ๋“œ ํ•„์š”
  • ํ‰๊ท  O(1) insert/find/remove

9-2. TSortedMap โ€” ์ •๋ ฌ๋œ ๋งต (RB-Tree ๊ฐ€ ์•„๋‹˜)

1
2
3
4
5
6
7
8
9
10
11
TSortedMap<int32, FString> Events;
Events.Add(300, TEXT("C"));
Events.Add(100, TEXT("A"));
Events.Add(200, TEXT("B"));

// ์ž๋™ ์ •๋ ฌ ์ˆœํšŒ
for (const auto& Pair : Events)
    UE_LOG(LogTemp, Log, TEXT("%d: %s"), Pair.Key, *Pair.Value);
// 100: A
// 200: B
// 300: C
  • ๋‚ด๋ถ€์ ์œผ๋กœ ์ •๋ ฌ๋œ TArray โ€” RB-Tree ๊ฐ€ ์•„๋‹˜
  • ์‚ฝ์ž…: O(n) (์ •๋ ฌ ์œ„์น˜์— ๋ผ์›Œ ๋„ฃ๊ธฐ)
  • ์กฐํšŒ: O(log n) (์ด์ง„ ํƒ์ƒ‰)
  • ์ž‘์€ N + ์กฐํšŒ ์œ„์ฃผ์—์„œ ์บ์‹œ ์นœํ™”๋กœ ๋” ๋น ๋ฅผ ์ˆ˜ ์žˆ์Œ

๊ฒŒ์ž„ ์—”์ง„ ์ฒ ํ•™ โ€” โ€œํŠธ๋ฆฌ ๋…ธ๋“œ ๋ถ„์‚ฐ ํ• ๋‹น๋ณด๋‹ค ์ •๋ ฌ ๋ฐฐ์—ด + ์ด์ง„ ํƒ์ƒ‰์ด ์บ์‹œ์ƒ ๋” ๋น ๋ฅผ ๋•Œ๊ฐ€ ๋งŽ๋‹คโ€.

9-3. TMultiMap โ€” ์ค‘๋ณต ํ‚ค ํ—ˆ์šฉ

1
2
3
4
5
6
7
8
TMultiMap<FString, int32> Scores;
Scores.Add("Alice", 85);
Scores.Add("Alice", 92);
Scores.Add("Alice", 78);

TArray<int32> AliceScores;
Scores.MultiFind("Alice", AliceScores);
// AliceScores: {85, 92, 78}

std::multimap + std::unordered_multimap ์˜ ํ†ตํ•ฉ ๋Œ€์‘. ๋‚ด๋ถ€๋Š” ํ•ด์‹œ ๊ธฐ๋ฐ˜.

9-4. UPROPERTY ยท GC ํ†ตํ•ฉ

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

    UPROPERTY()
    TMap<int32, AActor*> ActorsById; // ํ‚ค-๊ฐ’ ๋ชจ๋‘ ์ถ”์ 
};
  • UPROPERTY() ๋กœ ์„ ์–ธํ•˜๋ฉด GC ๊ฐ€ ์ปจํ…Œ์ด๋„ˆ ์•ˆ UObject ๊นŒ์ง€ ์ž๋™ ์ถ”์ 
  • ๋ธ”๋ฃจํ”„๋ฆฐํŠธ ๋…ธ์ถœ, ๋””ํ…Œ์ผ ํŒจ๋„ ํŽธ์ง‘ ๊ฐ€๋Šฅ
  • std::map<FName, UItem*> ์€ GC ๊ฐ€ ์ถ”์  ๋ชป ํ•ด ์–ธ๋ฆฌ์–ผ์—์„œ๋Š” ์ ˆ๋Œ€ ์“ฐ์ง€ ์•Š์Œ

9-5. STL โ†” ์–ธ๋ฆฌ์–ผ ์ปจํ…Œ์ด๋„ˆ ์ข…ํ•ฉํ‘œ

์นดํ…Œ๊ณ ๋ฆฌSTL์–ธ๋ฆฌ์–ผ๋น„๊ณ 
์ •๋ ฌ ๋งต (RB-Tree)std::map(์—†์Œ) โ€” TSortedMap ์œผ๋กœ ๋Œ€์ฒดRB ํŠธ๋ฆฌ ๋ฏธ์ฑ„ํƒ
ํ•ด์‹œ ๋งตstd::unordered_mapTMap โ˜… 1๊ธ‰ ์‹œ๋ฏผopen addressing
์ •๋ ฌ ์…‹ (RB-Tree)std::set(์—†์Œ) โ€” TSortedSet? TArray::Sortย 
ํ•ด์‹œ ์…‹std::unordered_setTSet โ˜… 1๊ธ‰ ์‹œ๋ฏผย 
์ค‘๋ณต ํ‚ค ๋งตstd::multimap / unordered_multimapTMultiMapย 

์–ธ๋ฆฌ์–ผ์€ TArray(vector) + TMap(unordered_map) + TSet(unordered_set) ์ด 1๊ธ‰ ์‹œ๋ฏผ์ด๊ณ , ํŠธ๋ฆฌ ๊ธฐ๋ฐ˜ ์ •๋ ฌ ์ปจํ…Œ์ด๋„ˆ๋Š” ๋ณด์กฐ์ ์ž…๋‹ˆ๋‹ค โ€” 13๋ฒˆ์—์„œ ๋ณธ std::list ์ฒ˜๋Ÿผ โ€œ์บ์‹œ ์ ๋Œ€์  ์ž๋ฃŒ๊ตฌ์กฐ ํšŒํ”ผโ€ ์ฒ ํ•™์ด ์ผ๊ด€๋ฉ๋‹ˆ๋‹ค.

9-6. TMap vs std::unordered_map ์ฐจ์ด์ 

ย std::unordered_mapTMap
์ถฉ๋Œ ํ•ด๊ฒฐSeparate Chaining (์ฒด์ธ)open addressing ๋ณ€ํ˜•
์บ์‹œ ์นœํ™”๋ณดํ†ต (์ฒด์ธ ๋…ธ๋“œ ๋ถ„์‚ฐ)๋” ์ข‹์Œ (๋ฐฐ์—ด ์ธ์ ‘ ์Šฌ๋กฏ)
๋ฉ”๋ชจ๋ฆฌ ์˜ค๋ฒ„ํ—ค๋“œ๋ฒ„ํ‚ท + ๋…ธ๋“œ (next ํฌ์ธํ„ฐ)์Šฌ๋กฏ ๋ฐฐ์—ด๋งŒ
GC ํ†ตํ•ฉ์—†์ŒUPROPERTY ๋กœ ์ž๋™ ์ถ”์ 
๋ฆฌํ”Œ๋ ‰์…˜์—†์Œ๋ธ”๋ฃจํ”„๋ฆฐํŠธ ์ž๋™ ๋…ธ์ถœ
ํ•ด์‹œ ํ•จ์ˆ˜std::hash<K> ํŠน์ˆ˜ํ™”GetTypeHash(K) ์˜ค๋ฒ„๋กœ๋“œ
๋น„๊ต ํ•จ์ˆ˜std::equal_to<K>operator== ์˜ค๋ฒ„๋กœ๋“œ

9-7. Algo:: ์™€ ์ •๋ ฌ

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});

// ํ‚ค ๊ธฐ์ค€ ์ •๋ ฌ โ€” std::sort ๋Œ€์‘
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; });

์ •๋ ฌ๋œ ๋ฐฐ์—ด + ์ด์ง„ ํƒ์ƒ‰ = ์‚ฌ์‹ค์ƒ TSortedMap ์˜ ๋‚ด๋ถ€ ๊ตฌ์กฐ.


10. ํšŒ๊ท€ ๋‹ค๋ฆฌ โ€” ๋‹ค๋ฅธ CS ํŒŒ์ผ ์—ฐ๊ฒฐ

10-1. 13๋ฒˆ [vector vs list] ์™€์˜ ์—ฐ๊ฒฐ

๋…ธ๋“œ ์•ˆ์ •์„ฑ์˜ ๋™์ผํ•œ ๋งฅ๋ฝ

13๋ฒˆ์—์„œ list ๊ฐ€ vector ๋Œ€๋น„ ์ •์งํ•œ ๊ฐ•์ ์ด๋ผ ๋ณธ ๋…ธ๋“œ ์•ˆ์ •์„ฑ์ด map ์—๋„ ๊ทธ๋Œ€๋กœ ์ ์šฉ๋ฉ๋‹ˆ๋‹ค.

1
2
3
4
5
6
7
8
std::map<int, std::string> m = {{1,"a"}, {2,"b"}, {3,"c"}};
auto it = m.find(2);

m.insert({4, "d"});       // โœ… it ๊ทธ๋Œ€๋กœ ์œ ํšจ (list ์™€ ๋™์ผ)
m.erase(1);               // โœ… it ๊ทธ๋Œ€๋กœ ์œ ํšจ
m.erase(it);              // โŒ it ๋ฌดํšจํ™” โ€” ๋ณธ์ธ ์‚ญ์ œ

// vector ์˜€๋‹ค๋ฉด push_back ํ•œ ๋ฒˆ์— ๋ชจ๋“  iterator ๊ฐ€ ๋ฌดํšจํ™” ๊ฐ€๋Šฅ

์ด๋Š” ๋ถ„์‚ฐ ๋…ธ๋“œ ์ž๋ฃŒ๊ตฌ์กฐ์˜ ๊ณตํ†ต ๊ฐ•์  โ€” ํŠธ๋ฆฌ๋“  ์—ฐ๊ฒฐ ๋ฆฌ์ŠคํŠธ๋“  ๋…ธ๋“œ๋ฅผ ํž™์— ๋ถ„์‚ฐ ํ• ๋‹นํ•˜๊ธฐ์— ๋”ฐ๋ผ์˜ต๋‹ˆ๋‹ค.

์บ์‹œ ์นœํ™”์„ฑ โ€” 13๋ฒˆ์˜ ํ•ต์‹ฌ ํŠธ๋ ˆ์ด๋“œ์˜คํ”„

1
2
3
4
5
์ˆœํšŒ ์„ฑ๋Šฅ:
  vector โ‰ซ unordered_map > map > list

13๋ฒˆ์—์„œ ๋ณธ vector ์˜ ์บ์‹œ ์นœํ™”์„ฑ์ด map ์—๋Š” ๋ถ€๋ถ„์ ์œผ๋กœ๋งŒ ์ ์šฉ๋จ.
ํŠธ๋ฆฌ ๋…ธ๋“œ๋Š” ๋ถ€๋ชจ-์ž์‹์ด ๋น„๊ต์  ๊ฐ€๊น์ง€๋งŒ ๋ถ„์‚ฐ ํ• ๋‹น ์ž์ฒด๋Š” ํ”ผํ•  ์ˆ˜ ์—†์Œ.

โ†’ ์ •๋ ฌยท๋ฒ”์œ„ ์กฐํšŒ๊ฐ€ ํ•„์š” ์—†์œผ๋ฉด unordered_map ์ด ํ•ญ์ƒ ๋” ๋น ๋ฅด๊ณ , ๋” ๋‚˜์•„๊ฐ€ ์ž‘์€ N ์—์„œ๋Š” ์ •๋ ฌ๋œ vector + ์ด์ง„ ํƒ์ƒ‰ ์ด ๊ฐ€์žฅ ๋น ๋ฅธ ๊ฒฝ์šฐ๊ฐ€ ๋งŽ์Œ.

10-2. 11๋ฒˆ [์Šค๋งˆํŠธ ํฌ์ธํ„ฐ] ์™€์˜ ์—ฐ๊ฒฐ

map<Key, unique_ptr<T>> ํŒจํ„ด

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

resources.emplace("config", std::make_unique<Resource>("config.dat"));
resources.try_emplace("save", std::make_unique<Resource>("save.dat"));

// ๊ฐ์ฒด ์ž์ฒด๋Š” ํž™์— ๊ณ ์ • โ†’ ์™ธ๋ถ€ ํฌ์ธํ„ฐ ์•ˆ์ •์„ฑ
Resource* p = resources["config"].get();
resources.erase("save");                    // โœ… p ์—ฌ์ „ํžˆ ์œ ํšจ
resources.emplace("temp", ...);             // โœ… p ์—ฌ์ „ํžˆ ์œ ํšจ (map ๋…ธ๋“œ๋งŒ ์ถ”๊ฐ€๋จ)

13๋ฒˆ์˜ vector<unique_ptr<T>> ํŒจํ„ด์ด map ์—์„œ๋Š” ๋” ์ž์—ฐ์Šค๋Ÿฝ์Šต๋‹ˆ๋‹ค โ€” map ์€ ์–ด์ฐจํ”ผ ๋…ธ๋“œ ์•ˆ์ •์„ฑ์„ ๊ฐ€์ง€๋ฏ€๋กœ ๊ฐ์ฒด ์•ˆ์ •์„ฑ๋„ ์ž๋™ ๋”ฐ๋ผ์˜ด.

try_emplace ์™€ unique_ptr

1
2
3
4
5
6
7
8
9
// operator[] ํ•จ์ • โ€” ์ž„์‹œ unique_ptr ์ƒ์„ฑ ํ›„ ํ‚ค ์žˆ์œผ๋ฉด ํŒŒ๊ดด
m["key"] = std::make_unique<Resource>("data");
// ๋งŒ์•ฝ "key" ๊ฐ€ ์ด๋ฏธ ์žˆ์œผ๋ฉด? โ†’ ๊ธฐ์กด unique_ptr ํŒŒ๊ดด + ์ƒˆ ๊ฒƒ ๋Œ€์ž…

// try_emplace โ€” ํ‚ค ์žˆ์œผ๋ฉด ์ธ์ž ์ž์ฒด๋ฅผ ๋งŒ๋“ค์ง€ ์•Š์Œ
auto [it, inserted] = m.try_emplace("key", std::make_unique<Resource>("data"));
if (!inserted) {
    // ์ด๋ฏธ ์กด์žฌ โ€” make_unique ๋„ ํ˜ธ์ถœ๋˜์ง€ ์•Š์Œ โ˜…
}

C++17 ์˜ ์ง„์งœ ๊ฐ€์น˜ โ€” ๋ฌด๋ธŒ-์˜จ๋ฆฌ ํƒ€์ž…์—์„œ ์˜๋„ ๋ช…ํ™•ํ•œ ์‚ฝ์ž….

10-3. 12๋ฒˆ [๋ณต์‚ฌ ๊ธˆ์ง€ยทmove-only] ์™€์˜ ์—ฐ๊ฒฐ

๋…ธ๋“œ ๋‹จ์œ„ ์•ˆ์ •์„ฑ โ†’ ๋ณต์‚ฌยท์ด๋™ ๋น„์šฉ ๋ถ„์„

1
2
3
4
5
6
7
std::map<std::string, BigObject> m;

m.emplace("A", /* BigObject ์ธ์ž */);  // ๋…ธ๋“œ ์•ˆ์—์„œ in-place ์ƒ์„ฑ
m.emplace("B", /* BigObject ์ธ์ž */);  // ๋‹ค๋ฅธ ๋…ธ๋“œ โ€” ๊ธฐ์กด ๋…ธ๋“œ ์˜ํ–ฅ ์—†์Œ

// vector ์™€ ๋‹ฌ๋ฆฌ ์žฌํ• ๋‹น์ด ์—†์œผ๋ฏ€๋กœ BigObject ์˜ noexcept move ์—ฌ๋ถ€ ๋ฌด๊ด€
// โ†’ ๋ณต์‚ฌยท์ด๋™ ์˜๋ฏธ๋ก ์— ๋œ ๋ฏผ๊ฐ

12๋ฒˆ์—์„œ ๋ณธ vector ์˜ noexcept move ์š”๊ตฌ์‚ฌํ•ญ์€ map ์—์„œ๋Š” ๊ฑฐ์˜ ๋ฌด๊ด€ โ€” ๋…ธ๋“œ๋ฅผ ์˜ฎ๊ธธ ์ผ์ด ์—†์œผ๋‹ˆ๊นŒ์š”.

10-4. 10๋ฒˆ [๋Œ•๊ธ€๋ง ํฌ์ธํ„ฐ] ์™€์˜ ์—ฐ๊ฒฐ

unordered_map rehash ๋ฌดํšจํ™” = ๋Œ•๊ธ€๋ง

1
2
3
4
5
6
7
std::unordered_map<int, int> u;
auto* p = &u[1];                    // p ๊ฐ€ (1, 100) ์˜ value ๊ฐ€๋ฆฌํ‚ด

for (int i = 0; i < 10000; ++i)
    u.insert({i, i});               // โ˜… rehash ๋ฐœ์ƒ โ†’ ๋ชจ๋“  ํฌ์ธํ„ฐ ๋ฌดํšจ

*p = 99;                            // โŒ ๋Œ•๊ธ€๋ง โ€” 10๋ฒˆ์—์„œ ๋ณธ ํŒจํ„ด

13๋ฒˆ vector ์žฌํ• ๋‹น๊ณผ ๋™์ผํ•œ ํŒจํ„ด โ€” ์—ฐ์† ๋ฉ”๋ชจ๋ฆฌ/๋ฒ„ํ‚ท ๋ฐฐ์—ด ์ž๋ฃŒ๊ตฌ์กฐ์˜ ๊ณตํ†ต ํ•จ์ •.

โ†’ map ์€ ๋…ธ๋“œ ์•ˆ์ •์„ฑ์œผ๋กœ ์ด ํ•จ์ •์ด ์—†์Œ โ€” ํŠธ๋ฆฌ๋งต์„ ์„ ํƒํ•˜๋Š” ๋˜ ํ•˜๋‚˜์˜ ์•ˆ์ „์„ฑ ์ด์œ .

10-5. 09๋ฒˆ [RAII] ์™€์˜ ์—ฐ๊ฒฐ

map ์ž์ฒด๊ฐ€ RAII:

1
2
3
4
5
6
{
    std::map<std::string, std::unique_ptr<Resource>> resources;
    resources.emplace("a", std::make_unique<Resource>(...));
    resources.emplace("b", std::make_unique<Resource>(...));
    // ...
}   // ์Šค์ฝ”ํ”„ ์ข…๋ฃŒ โ†’ map ์†Œ๋ฉธ์ž โ†’ ๋ชจ๋“  ๋…ธ๋“œ + ๋ชจ๋“  unique_ptr ์ž๋™ ํ•ด์ œ
  • ์ปจํ…Œ์ด๋„ˆ ์ž์ฒด๊ฐ€ ์ž์› ๊ด€๋ฆฌ
  • ์•ˆ์˜ ์Šค๋งˆํŠธ ํฌ์ธํ„ฐ๊ฐ€ ๊ฐ์ฒด ์ˆ˜๋ช… ๊ด€๋ฆฌ
  • ๋‘ RAII ๊ฐ€ ํ•ฉ์ณ์ ธ ๋ˆ„์ˆ˜ 0 ๋ณด์žฅ

13๋ฒˆ vector ์™€ ๋™์ผํ•œ RAII ์‚ฌ๋ก€.

10-6. 04-29(์˜ค๋Š˜) ํšŒ๊ณ  โ€” 13๋ฒˆ โ†’ 14๋ฒˆ ์ž์—ฐ ํ๋ฆ„

1
2
3
4
5
6
7
13๋ฒˆ ํ•ต์‹ฌ ๊ฐœ๋…                  14๋ฒˆ์—์„œ์˜ ํ™œ์šฉ
โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€
์—ฐ์† ๋ฉ”๋ชจ๋ฆฌ vs ๋ถ„์‚ฐ ๋…ธ๋“œ     โ†’  map(๋ถ„์‚ฐ ํŠธ๋ฆฌ), unordered_map(๋ถ„์‚ฐ+๋ฒ„ํ‚ท)
์บ์‹œ ์นœํ™”์„ฑ (vector ์••์Šน)    โ†’  vector โ‰ซ unordered_map > map > list
iterator ๋ฌดํšจํ™” ํŠธ๋ ˆ์ด๋“œ์˜คํ”„ โ†’  map ๋…ธ๋“œ ์•ˆ์ • > unordered_map rehash ๋ฌดํšจ
amortized O(1) (push_back)   โ†’  map insert(hint) ๋„ amortized O(1)
"์˜์‹ฌ์Šค๋Ÿฌ์šฐ๋ฉด vector"        โ†’  "์˜์‹ฌ์Šค๋Ÿฌ์šฐ๋ฉด unordered_map" โ€” ์ •๋ ฌ ํ•„์š”์‹œ๋งŒ map

14๋ฒˆ์€ 13๋ฒˆ์˜ ์บ์‹œยท๋ณต์žก๋„ ๋ถ„์„ ํ”„๋ ˆ์ž„์„ ์—ฐ๊ด€ ์ปจํ…Œ์ด๋„ˆ์— ์ ์šฉํ•œ ์‘์šฉํŽธ์ž…๋‹ˆ๋‹ค. ๋‹ค์Œ ์ฃผ์ œ(STL ์•Œ๊ณ ๋ฆฌ์ฆ˜ยท์ •๋ ฌยทํ•ด์‹œ ํ•จ์ˆ˜) ๋กœ ์ž์—ฐ์Šค๋Ÿฝ๊ฒŒ ์ด์–ด์ง‘๋‹ˆ๋‹ค.


11. ๊ผฌ๋ฆฌ์งˆ๋ฌธ ์˜ˆ์ƒ ๊ฒฝ๋กœ

๋ฉ”์ธ ์งˆ๋ฌธ ๋‹ต๋ณ€ ํ›„ ์˜ˆ์ƒ ํ๋ฆ„

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
"std::map ์€ ์–ด๋–ป๊ฒŒ ๋™์ž‘ํ•˜๋‚˜์š”?"
         โ”‚
         โ”œโ”€ ๋‚ด๋ถ€ ์ž๋ฃŒ๊ตฌ์กฐ (โ˜… ๊ฐ€์žฅ ๊นŠ์ด)
         โ”‚    โ”œโ”€ "Red-Black Tree ๊ฐ€ ๋ญ”๊ฐ€์š”?"
         โ”‚    โ”‚    โ””โ”€ "5๊ฐ€์ง€ ์†์„ฑ์„ ๋‹ค ๋งํ•ด๋ณด์„ธ์š”"
         โ”‚    โ”œโ”€ "์™œ BST ๊ฐ€ ์•„๋‹Œ ์ž๊ธฐ ๊ท ํ˜• BST ์ธ๊ฐ€์š”?"
         โ”‚    โ”œโ”€ "AVL ๊ณผ ๋น„๊ตํ•˜๋ฉด?"
         โ”‚    โ””โ”€ "ํšŒ์ „ ์ข…๋ฅ˜๋Š”?"
         โ”‚
         โ”œโ”€ ์‹œ๊ฐ„ ๋ณต์žก๋„
         โ”‚    โ”œโ”€ "์™œ O(log n) ์ธ๊ฐ€์š”?"
         โ”‚    โ”œโ”€ "operator[] ๊ฐ€ O(log n) ์ธ ์ด์œ ?"
         โ”‚    โ””โ”€ "lower_bound / upper_bound ๋Š”?"
         โ”‚
         โ”œโ”€ unordered_map ๋น„๊ต (โ˜… ๊ฐ€์žฅ ์ž์ฃผ)
         โ”‚    โ”œโ”€ "์–ธ์ œ ์–ด๋–ค ๊ฑธ ์“ฐ๋‚˜์š”?"
         โ”‚    โ”œโ”€ "unordered_map ์ตœ์•…์ด O(n) ์ธ ์ด์œ ?"
         โ”‚    โ”œโ”€ "rehash ๊ฐ€ ๋ญ”๊ฐ€์š”?"
         โ”‚    โ””โ”€ "๋ฒ”์œ„ ์กฐํšŒ๋Š”?"
         โ”‚
         โ”œโ”€ iterator / ์•ˆ์ •์„ฑ
         โ”‚    โ”œโ”€ "์‚ฝ์ž…ํ•  ๋•Œ iterator ๊ฐ€ ๋ฌดํšจํ™”๋˜๋‚˜์š”?"
         โ”‚    โ””โ”€ "vector ์™€ ์–ด๋–ป๊ฒŒ ๋‹ค๋ฅด์ฃ ?" (โ˜… 13๋ฒˆ ํšŒ๊ท€)
         โ”‚
         โ”œโ”€ operator[]
         โ”‚    โ”œโ”€ "const map ์—์„œ ์™œ ๋ชป ์“ฐ๋‚˜์š”?"
         โ”‚    โ””โ”€ "at ๊ณผ ์ฐจ์ด๋Š”?"
         โ”‚
         โ”œโ”€ ๋ฉ”๋ชจ๋ฆฌ ์˜ค๋ฒ„ํ—ค๋“œ
         โ”‚    โ”œโ”€ "๋…ธ๋“œ ํ•˜๋‚˜์˜ ํฌ๊ธฐ๋Š”?"
         โ”‚    โ””โ”€ "์บ์‹œ ์นœํ™”์„ฑ์€?"
         โ”‚
         โ””โ”€ ์–ธ๋ฆฌ์–ผ
              โ”œโ”€ "TMap ์€ std::map ์ธ๊ฐ€์š”?"
              โ”œโ”€ "TSortedMap ์€?"
              โ””โ”€ "์™œ RB-Tree ์ปจํ…Œ์ด๋„ˆ๊ฐ€ 1๊ธ‰์ด ์•„๋‹Œ๊ฐ€์š”?"

๊ฐ ๊ผฌ๋ฆฌ์งˆ๋ฌธ 30์ดˆ ๋‹ต๋ณ€

Q: std::map ์˜ ๋‚ด๋ถ€ ์ž๋ฃŒ๊ตฌ์กฐ๋Š”?

1
2
3
4
5
๊ฑฐ์˜ ๋ชจ๋“  ํ‘œ์ค€ ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ ๊ตฌํ˜„์—์„œ Red-Black Tree (์ž๊ธฐ ๊ท ํ˜• BST).
๋…ธ๋“œ์— ๋นจ๊ฐ•/๊ฒ€์ • ์ƒ‰๊น”์„ ๋ถ€์—ฌํ•˜๊ณ  5๊ฐ€์ง€ ์†์„ฑ์„ ์œ ์ง€ํ•ด
ํŠธ๋ฆฌ ๋†’์ด๋ฅผ ํ•ญ์ƒ O(log n) ๋กœ ๋ณด์žฅ.

โ†’ insert / erase / find ๋ชจ๋‘ O(log n) ์ตœ์•… ๋ณด์žฅ.

Q: Red-Black Tree 5๊ฐ€์ง€ ์†์„ฑ?

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

์ด ์†์„ฑ๋“ค๋กœ ํŠธ๋ฆฌ ๋†’์ด๊ฐ€ ์ตœ์•… 2 log(n+1) ๋กœ ์ œํ•œ๋จ.

Q: AVL ๊ณผ RB ํŠธ๋ฆฌ ์ค‘ ๋ญ๊ฐ€ ๋” ์ข‹์€๊ฐ€์š”?

1
2
3
4
5
AVL โ€” ๋” ์—„๊ฒฉํ•œ ๊ท ํ˜• (๋†’์ด ์ฐจ 1 ์ดํ•˜) โ†’ ๊ฒ€์ƒ‰ ์•ฝ๊ฐ„ ๋น ๋ฆ„
RB  โ€” ๋А์Šจํ•œ ๊ท ํ˜• (์ƒ‰๊น” 5์†์„ฑ) โ†’ ํšŒ์ „ ํšŸ์ˆ˜ ์ ์Œ, ์‚ฝ์ž…/์‚ญ์ œ ๋น ๋ฆ„

STL map/set ์ด RB ๋ฅผ ์„ ํƒํ•œ ์ด์œ ๋Š” ์ผ๋ฐ˜ ๋ชฉ์ ์ด๊ณ  ๊ฐฑ์‹ ๋„ ์ž์ฃผ ์žˆ์–ด์„œ.
๊ฒ€์ƒ‰ ๋น„์ค‘์ด ์••๋„์ ์ด๋ฉด AVL, ๊ฐฑ์‹ ๋„ ๋งŽ์œผ๋ฉด RB.

Q: ์ƒˆ ๋…ธ๋“œ๋Š” ์™œ ๋นจ๊ฐ•์œผ๋กœ ์‚ฝ์ž…ํ•˜๋‚˜์š”?

1
2
3
4
5
6
7
๊ฒ€์ •์œผ๋กœ ์‚ฝ์ž…ํ•˜๋ฉด ๊ทธ ๊ฒฝ๋กœ์˜ black height ๊ฐ€ 1 ์ฆ๊ฐ€ โ†’ ์†์„ฑ 5 ์œ„๋ฐ˜ โ†’
๋‹ค๋ฅธ ๋ชจ๋“  ๊ฒฝ๋กœ๋„ ๋งž์ถฐ์•ผ ํ•ด ๋น„์‹ธ์ง.

๋นจ๊ฐ•์œผ๋กœ ์‚ฝ์ž…ํ•˜๋ฉด black height ๋ณ€ํ™” ์—†์Œ โ†’ ์œ„๋ฐ˜ ๊ฐ€๋Šฅ์„ฑ์€ R-R ๋ฟ โ†’
๊ตญ์†Œ์ ์ธ ํšŒ์ „ยท์žฌ์ƒ‰์น ๋กœ ๋ณต๊ตฌ ๊ฐ€๋Šฅ.

๋ณต๊ตฌ ๋น„์šฉ ์ตœ์†Œํ™”์˜ ์˜๋ฆฌํ•œ ์„ ํƒ.

Q: map ๊ณผ unordered_map ์–ธ์ œ ์–ด๋–ค ๊ฑธ ์“ฐ๋‚˜์š”? (โ˜… ๊ฐ€์žฅ ์ž์ฃผ)

1
2
3
4
5
6
7
8
9
10
11
12
13
map ์„ ํƒ:
  - ํ‚ค ์ •๋ ฌ์ด ๊ฒฐ๊ณผ์ ์œผ๋กœ ํ•„์š”
  - ๋ฒ”์œ„ ์กฐํšŒ (lower_bound / upper_bound)
  - ์ตœ์•… ์‹œ๊ฐ„ ๋ณด์žฅ ํ•„์š” (์‹ค์‹œ๊ฐ„ ์‹œ์Šคํ…œ)
  - ํ‚ค์— ํ•ด์‹œ ํ•จ์ˆ˜ ์ •์˜ ์–ด๋ ค์›€

unordered_map ์„ ํƒ:
  - ์ˆœ์„œ ๋ฌด๊ด€, ์ตœ๋Œ€ ์ฒ˜๋ฆฌ๋Ÿ‰ ์šฐ์„ 
  - ํ‚ค๊ฐ€ ํ•ด์‹œ ํ•จ์ˆ˜์— ์ž˜ ๋ถ„ํฌ (์ •์ˆ˜, ๋ฌธ์ž์—ด)
  - ํ‰๊ท  O(1) ์˜ ์ด์  ์ถฉ๋ถ„ํžˆ ํ™œ์šฉ
  - rehash ๋ฌดํšจํ™”๋ฅผ ์‹ ๊ฒฝ ์•ˆ ์จ๋„ ๋จ

์š”์•ฝ: ์ •๋ ฌยท๋ฒ”์œ„ยท์ตœ์•… ๋ณด์žฅ โ†’ map / ๋น ๋ฅธ ์กฐํšŒ โ†’ unordered_map

Q: unordered_map ์˜ ์ตœ์•… O(n) ์€ ์™œ ๋ฐœ์ƒํ•˜๋‚˜์š”?

1
2
3
4
5
6
ํ•ด์‹œ ์ถฉ๋Œ โ€” ๋‹ค๋ฅธ ํ‚ค๊ฐ€ ๊ฐ™์€ ๋ฒ„ํ‚ท์— ๋งคํ•‘๋จ.
์ฒด์ด๋‹ ๋ฐฉ์‹์ด๋ผ ๊ฐ™์€ ๋ฒ„ํ‚ท์˜ ์›์†Œ๊ฐ€ ์—ฐ๊ฒฐ ๋ฆฌ์ŠคํŠธ๋กœ ๋ฌถ์ž„.
๋ชจ๋“  ํ‚ค๊ฐ€ ๊ฐ™์€ ๋ฒ„ํ‚ท์— ๋ชฐ๋ฆฌ๋ฉด ์‚ฌ์‹ค์ƒ ์—ฐ๊ฒฐ ๋ฆฌ์ŠคํŠธ โ†’ O(n).

์•…์˜์  ์ž…๋ ฅ (ํ•ด์‹œ DoS) ๋˜๋Š” ๋‚˜์œ ํ•ด์‹œ ํ•จ์ˆ˜๊ฐ€ ์›์ธ.
๋ฐฉ์–ด: ์ข‹์€ ํ•ด์‹œ ํ•จ์ˆ˜ + ์ ์ ˆํ•œ max_load_factor.

Q: rehash ๊ฐ€ ๋ญ”๊ฐ€์š”?

1
2
3
4
5
6
7
8
9
10
unordered_map ์˜ load_factor (size / bucket_count) ๊ฐ€ ์ž„๊ณ„๊ฐ’ ์ดˆ๊ณผ ์‹œ:
  1) ๋” ํฐ ๋ฒ„ํ‚ท ๋ฐฐ์—ด ํ• ๋‹น (๋ณดํ†ต 2๋ฐฐ)
  2) ๋ชจ๋“  ์›์†Œ๋ฅผ ์ƒˆ ํ•ด์‹œ๊ฐ’์œผ๋กœ ์žฌ๋ฐฐ์น˜
  3) ๊ธฐ์กด ๋ฒ„ํ‚ท ๋ฐฐ์—ด ํ•ด์ œ

๋น„์šฉ O(n) โ€” 13๋ฒˆ vector ์žฌํ• ๋‹น๊ณผ ๋™์ผํ•œ ํŒจํ„ด.
๋ชจ๋“  iteratorยทํฌ์ธํ„ฐยท์ฐธ์กฐ ๋ฌดํšจํ™” โ€” ๋Œ•๊ธ€๋ง ์œ„ํ—˜.
ํšŒํ”ผ: u.reserve(n) ์œผ๋กœ ๋ฏธ๋ฆฌ ๋ฒ„ํ‚ท ํ™•๋ณด.

map ์€ ์ด๋Ÿฐ ์ผ์ด ์—†์Œ โ€” ๋…ธ๋“œ ์•ˆ์ •์„ฑ์ด ๊ฒฐ์ •์  ์ฐจ์ด.

Q: lower_bound ์™€ upper_bound ์ฐจ์ด?

1
2
3
4
5
6
7
8
9
10
11
12
lower_bound(k) โ€” k ์ด์ƒ์ธ ์ฒซ ์›์†Œ์˜ iterator
upper_bound(k) โ€” k ์ดˆ๊ณผ์ธ ์ฒซ ์›์†Œ์˜ iterator
equal_range(k) โ€” [lower, upper) ์Œ ๋ฐ˜ํ™˜

์˜ˆ: m = {1, 3, 5, 7}
  lower_bound(3) โ†’ 3
  upper_bound(3) โ†’ 5
  lower_bound(4) โ†’ 5
  upper_bound(4) โ†’ 5
  โ†’ equal_range(3) = [3, 5), equal_range(4) = [5, 5) (๋นˆ ๋ฒ”์œ„)

ํ•ด์‹œ๋งต์—๋Š” ์—†๋Š” ๊ฐ•๋ ฅํ•œ ์—ฐ์‚ฐ โ€” ์ •๋ ฌ ์ปจํ…Œ์ด๋„ˆ์˜ ์ •์งํ•œ ๊ฐ•์ .

Q: vector ์˜ iterator ๋ฌดํšจํ™”์™€ ์–ด๋–ค ์ฐจ์ด? (โ˜… 13๋ฒˆ ํšŒ๊ท€)

1
2
3
4
5
6
7
vector โ€” ์žฌํ• ๋‹น ์‹œ ๋ชจ๋“  iterator/ํฌ์ธํ„ฐ/์ฐธ์กฐ ๋ฌดํšจ
         insert/erase ์‹œ ์œ„์น˜ ์ดํ›„ ๋ฌดํšจ
map    โ€” ์‚ฝ์ž…์€ ๋ฌดํšจํ™” ์—†์Œ (โ˜…)
         ์‚ญ์ œ๋Š” ์‚ญ์ œ๋œ ๋…ธ๋“œ๋งŒ ๋ฌดํšจ

13๋ฒˆ์—์„œ ๋ณธ list ์˜ ๋…ธ๋“œ ์•ˆ์ •์„ฑ๊ณผ ๋™์ผ โ€” ๋ถ„์‚ฐ ๋…ธ๋“œ ์ž๋ฃŒ๊ตฌ์กฐ์˜ ๊ณตํ†ต ๊ฐ•์ .
์ด ์ฐจ์ด๋กœ map ์€ ์™ธ๋ถ€์— iterator ๋ฅผ ์ €์žฅํ•ด ๋‘๋Š” ํŒจํ„ด์ด ์•ˆ์ „ํ•จ.

Q: operator[] ๊ฐ€ const map ์—์„œ ๋ชป ์“ฐ๋Š” ์ด์œ ?

1
2
3
4
5
6
7
operator[](k) ๋Š” ํ‚ค๊ฐ€ ์—†์œผ๋ฉด default(T) ๋ฅผ ์ž๋™ ์‚ฝ์ž….
์ฆ‰ mutating ์—ฐ์‚ฐ์ด๋ผ const ๊ฐ์ฒด์—์„œ๋Š” ํ˜ธ์ถœ ๋ถˆ๊ฐ€.

const map ์—์„œ๋Š” at(k) ์‚ฌ์šฉ โ€” ์—†์œผ๋ฉด std::out_of_range ์˜ˆ์™ธ.
๋˜๋Š” find(k) ๋กœ iterator ๋ฐ›๊ณ  != end() ์ฒดํฌ.

์ด ํ•จ์ • ๋•Œ๋ฌธ์— ๊ฐ€๋Šฅํ•˜๋ฉด operator[] ๋ณด๋‹ค try_emplace / find / at ๊ถŒ์žฅ.

Q: TMap ์€ std::map ์ธ๊ฐ€์š”?

1
2
3
4
5
6
7
8
์•„๋‹™๋‹ˆ๋‹ค โ€” TMap ์€ ํ•ด์‹œ ๊ธฐ๋ฐ˜์œผ๋กœ std::unordered_map ์— ๋” ๊ฐ€๊นŒ์›Œ์š”.

std::map (RB-Tree) ์— ์ง์ ‘ ๋Œ€์‘ํ•˜๋Š” 1๊ธ‰ ์ปจํ…Œ์ด๋„ˆ๋Š” ์—†๊ณ ,
์ •๋ ฌ์ด ํ•„์š”ํ•˜๋ฉด TSortedMap ์„ ์‚ฌ์šฉ. ๋‹จ TSortedMap ๋„ RB-Tree ๊ฐ€ ์•„๋‹Œ
์ •๋ ฌ๋œ TArray ๊ธฐ๋ฐ˜ โ€” ์ž‘์€ N ์—์„œ ์บ์‹œ ์นœํ™”์ .

์–ธ๋ฆฌ์–ผ์ด RB-Tree ๋ฅผ 1๊ธ‰์œผ๋กœ ๋‘์ง€ ์•Š์€ ์ด์œ ๋Š” ๊ฒŒ์ž„ ์—”์ง„ ํŠน์„ฑ์ƒ
์บ์‹œ ์นœํ™”์„ฑ์ด ์šฐ์„ ์ด๋ผ ํŠธ๋ฆฌ ๋…ธ๋“œ ๋ถ„์‚ฐ์„ ํ”ผํ•˜๋ ค๋Š” ์˜๋„.

Q: try_emplace ๊ฐ€ emplace ์™€ ๋‹ค๋ฅธ ์ ?

1
2
3
4
5
6
7
8
emplace(k, args...) โ€” ํ•ญ์ƒ ๋…ธ๋“œ ์ƒ์„ฑ ์‹œ๋„, ํ‚ค ์žˆ์œผ๋ฉด ๋ฌด์‹œ๋˜์ง€๋งŒ
                       args ๋กœ ๋งŒ๋“  ์ž„์‹œ ๊ฐ์ฒด๋Š” ์ด๋ฏธ ์ƒ์„ฑ๋จ

try_emplace(k, args...) (C++17) โ€” ํ‚ค ์žˆ์œผ๋ฉด args ์ž์ฒด๋ฅผ ๋งŒ๋“ค์ง€ ์•Š์Œ
                                  ๋ฌด๋ธŒ-์˜จ๋ฆฌ ํƒ€์ž…(unique_ptr ๋“ฑ) ์—์„œ ํŠนํžˆ ์œ ์šฉ

operator[] ์˜ default ์‚ฝ์ž… ํŠธ๋žฉ ํšŒํ”ผ + emplace ์˜ ์ž„์‹œ ๊ฐ์ฒด ํŠธ๋žฉ ํšŒํ”ผ
โ†’ "์žˆ์œผ๋ฉด ๊ทธ๋Œ€๋กœ, ์—†์„ ๋•Œ๋งŒ ์‚ฝ์ž…" ์˜๋„๋ฅผ ๊ฐ€์žฅ ๋ช…ํ™•ํ•˜๊ฒŒ ํ‘œํ˜„.

12. ๋ชจ์˜๋ฉด์ ‘ ๋‹ต๋ณ€ ํ…œํ”Œ๋ฆฟ (1๋ถ„ / 3๋ถ„)

12-1. 1๋ถ„ ๋ฒ„์ „ โ€” ํ•ต์‹ฌ๋งŒ

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
std::map ์€ ํ‚ค-๊ฐ’ ์Œ์„ ํ‚ค ๊ธฐ์ค€์œผ๋กœ ์ž๋™ ์ •๋ ฌํ•ด ์ €์žฅํ•˜๋Š” ์—ฐ๊ด€ ์ปจํ…Œ์ด๋„ˆ๋กœ,
๋‚ด๋ถ€์ ์œผ๋กœ Red-Black Tree (์ž๊ธฐ ๊ท ํ˜• BST) ๋ฅผ ์‚ฌ์šฉํ•ฉ๋‹ˆ๋‹ค. ๊ทธ๋ž˜์„œ
insert / erase / find ๋ชจ๋‘ O(log n) ์ตœ์•… ๋ณด์žฅ์ž…๋‹ˆ๋‹ค.

Red-Black Tree ๋Š” ๋…ธ๋“œ์— ๋นจ๊ฐ•ยท๊ฒ€์ • ์ƒ‰๊น”์„ ๋ถ€์—ฌํ•˜๊ณ  5๊ฐ€์ง€ ์†์„ฑ์œผ๋กœ
ํŠธ๋ฆฌ ๋†’์ด๋ฅผ O(log n) ์œผ๋กœ ์œ ์ง€ํ•ฉ๋‹ˆ๋‹ค. ํ•ต์‹ฌ์€ ๋นจ๊ฐ• ๋…ธ๋“œ๊ฐ€ ์—ฐ์†์œผ๋กœ
๋‚˜์˜ฌ ์ˆ˜ ์—†๋‹ค๋Š” ๊ฒƒ๊ณผ ๋ชจ๋“  NIL ๊นŒ์ง€์˜ ๊ฒฝ๋กœ์˜ ๊ฒ€์ • ๋…ธ๋“œ ์ˆ˜๊ฐ€ ๋™์ผํ•ด์•ผ
ํ•œ๋‹ค๋Š” ๊ฒƒ์ด๊ณ , ์‚ฝ์ž…ยท์‚ญ์ œ ์‹œ ํšŒ์ „๊ณผ ์žฌ์ƒ‰์น ๋กœ ์ด ์†์„ฑ์„ ๋ณต๊ตฌํ•ฉ๋‹ˆ๋‹ค.

๋น„์Šทํ•œ ์˜์—ญ์˜ unordered_map ์€ ํ•ด์‹œ ํ…Œ์ด๋ธ” ๊ธฐ๋ฐ˜์œผ๋กœ ํ‰๊ท  O(1)
์ด์ง€๋งŒ ์ •๋ ฌ์ด ์•ˆ ๋˜๊ณ  ์ตœ์•…์€ O(n) ์ž…๋‹ˆ๋‹ค. ๋”ฐ๋ผ์„œ ์ •๋ ฌยท๋ฒ”์œ„ ์กฐํšŒยท
์ตœ์•… ์‹œ๊ฐ„ ๋ณด์žฅ์ด ํ•„์š”ํ•˜๋ฉด map, ์ˆœ์„œ ๋ฌด๊ด€ + ์ตœ๋Œ€ ์ฒ˜๋ฆฌ๋Ÿ‰์ด ์ค‘์š”ํ•˜๋ฉด
unordered_map ์„ ์„ ํƒํ•ฉ๋‹ˆ๋‹ค.

iterator ๋ฌดํšจํ™” ๋ฉด์—์„œ๋„ map ์€ list ์™€ ๊ฐ™์€ ๋…ธ๋“œ ์•ˆ์ •์„ฑ์„ ๊ฐ€์ ธ
์‚ฝ์ž…์€ ๋ฌดํšจํ™”๊ฐ€ ์ „ํ˜€ ์—†๊ณ  ์‚ญ์ œ๋„ ์‚ญ์ œ๋œ ๋…ธ๋“œ๋งŒ ๋ฌดํšจํ™”๋ฉ๋‹ˆ๋‹ค.
์ด๊ฒŒ vector ์˜ ์žฌํ• ๋‹น ๋ฌดํšจํ™”์™€ ์ •๋ฐ˜๋Œ€ ํŠธ๋ ˆ์ด๋“œ์˜คํ”„์ž…๋‹ˆ๋‹ค.

12-2. 3๋ถ„ ๋ฒ„์ „ โ€” RB-Treeยทunorderedยท์–ธ๋ฆฌ์–ผ๊นŒ์ง€

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
72
73
74
75
[1] std::map ์€ ์ •๋ ฌ๋œ ์—ฐ๊ด€ ์ปจํ…Œ์ด๋„ˆ์ž…๋‹ˆ๋‹ค.

ํ‚ค-๊ฐ’ ์Œ์„ ํ‚ค ๊ธฐ์ค€์œผ๋กœ ์ž๋™ ์ •๋ ฌํ•ด ์ €์žฅํ•˜๊ณ  ํ‚ค ์ค‘๋ณต์€ ํ—ˆ์šฉํ•˜์ง€
์•Š์Šต๋‹ˆ๋‹ค. ๋‚ด๋ถ€ ์ž๋ฃŒ๊ตฌ์กฐ๋Š” ๊ฑฐ์˜ ๋ชจ๋“  ํ‘œ์ค€ ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ ๊ตฌํ˜„์—์„œ
Red-Black Tree (์ž๊ธฐ ๊ท ํ˜• BST) ์ž…๋‹ˆ๋‹ค. ์‹œ๊ทธ๋‹ˆ์ฒ˜๋Š”
std::map<Key, T, Compare, Allocator> ์ด๊ณ , ์ •๋ ฌ ๊ธฐ์ค€์€ ๊ธฐ๋ณธ์ ์œผ๋กœ
std::less<Key> ์ž…๋‹ˆ๋‹ค.

์›์†Œ ํƒ€์ž…์ด std::pair<const Key, T> ๋ผ๋Š” ์ ์ด ํŠน์ง•์ธ๋ฐ, ํ‚ค๊ฐ€
const ์ธ ์ด์œ ๋Š” ๋ณ€๊ฒฝํ•˜๋ฉด ํŠธ๋ฆฌ ์ •๋ ฌ ์ˆœ์„œ๊ฐ€ ๊นจ์ง€๊ธฐ ๋•Œ๋ฌธ์ž…๋‹ˆ๋‹ค.
๊ฐ’๋งŒ ์ˆ˜์ • ๊ฐ€๋Šฅํ•ฉ๋‹ˆ๋‹ค.

[2] ํ•ต์‹ฌ์€ Red-Black Tree ์˜ 5๊ฐ€์ง€ ์†์„ฑ์ž…๋‹ˆ๋‹ค.

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

์ด ์†์„ฑ๋“ค์ด ํŠธ๋ฆฌ ๋†’์ด๋ฅผ ์ตœ์•… 2 log(n+1) ๋กœ ์ œํ•œํ•ด ๋ชจ๋“  ํ•ต์‹ฌ ์—ฐ์‚ฐ์ด
O(log n) ๋ณด์žฅ๋ฉ๋‹ˆ๋‹ค. ์‚ฝ์ž…ยท์‚ญ์ œ ์‹œ ์†์„ฑ์ด ๊นจ์ง€๋ฉด ํšŒ์ „๊ณผ ์žฌ์ƒ‰์น ๋กœ
๋ณต๊ตฌํ•˜๋Š”๋ฐ, ์ƒˆ ๋…ธ๋“œ๋Š” ํ•ญ์ƒ ๋นจ๊ฐ•์œผ๋กœ ์‚ฝ์ž…ํ•ฉ๋‹ˆ๋‹ค โ€” ๊ทธ๋ž˜์•ผ black height
๊ฐ€ ๋ณ€ํ•˜์ง€ ์•Š์•„ ๋ณต๊ตฌ ๋น„์šฉ์ด ์ตœ์†Œํ™”๋˜๊ฑฐ๋“ ์š”.

๋น„์Šทํ•œ ์ž๊ธฐ ๊ท ํ˜• BST ์ธ AVL ๊ณผ ๋น„๊ตํ•˜๋ฉด, AVL ์€ ๋” ์—„๊ฒฉํ•œ ๊ท ํ˜•์œผ๋กœ
๊ฒ€์ƒ‰์ด ์•ฝ๊ฐ„ ๋น ๋ฅด์ง€๋งŒ ํšŒ์ „ ํšŸ์ˆ˜๊ฐ€ ๋งŽ์•„ ๊ฐฑ์‹ ์ด ๋А๋ฆฝ๋‹ˆ๋‹ค. RB ๋Š” ๋А์Šจํ•œ
๊ท ํ˜• ๋Œ€์‹  ํšŒ์ „์ด ์ ์–ด ์‚ฝ์ž…ยท์‚ญ์ œ ์œ„์ฃผ์—์„œ ์œ ๋ฆฌํ•ฉ๋‹ˆ๋‹ค. STL ์€ ์ผ๋ฐ˜
๋ชฉ์ ์ด๋ผ RB ๋ฅผ ์ฑ„ํƒํ–ˆ์Šต๋‹ˆ๋‹ค.

[3] unordered_map ๊ณผ์˜ ๋น„๊ต๊ฐ€ ๊ฐ€์žฅ ์ž์ฃผ ๋‚˜์˜ต๋‹ˆ๋‹ค.

unordered_map ์€ ํ•ด์‹œ ํ…Œ์ด๋ธ” ๊ธฐ๋ฐ˜์œผ๋กœ ํ‰๊ท  O(1) ์ด์ง€๋งŒ ์ตœ์•…์€
O(n) ์ž…๋‹ˆ๋‹ค (ํ•ด์‹œ ์ถฉ๋Œ). ์ •๋ ฌ์ด ์•ˆ ๋˜๊ณ , lower_bound ๊ฐ™์€ ๋ฒ”์œ„ ์กฐํšŒ๋„
์ง€์›ํ•˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค. ๋ฉ”๋ชจ๋ฆฌ ์˜ค๋ฒ„ํ—ค๋“œ๋„ ๋ฒ„ํ‚ท ๋ฐฐ์—ด + ์ฒด์ด๋‹ ๋…ธ๋“œ๋กœ
๋” ํฝ๋‹ˆ๋‹ค.

์„ ํƒ ๊ธฐ์ค€์€ ๋ช…ํ™•ํ•ฉ๋‹ˆ๋‹ค. ํ‚ค ์ •๋ ฌ์ด ํ•„์š”ํ•˜๊ฑฐ๋‚˜, ๋ฒ”์œ„ ์กฐํšŒ๋ฅผ ํ•ด์•ผ ํ•˜๊ฑฐ๋‚˜,
์ตœ์•… ์‹œ๊ฐ„ ๋ณด์žฅ์ด ํ•„์š”ํ•œ ์‹œ์Šคํ…œ์ด๋ฉด map. ์ˆœ์„œ ๋ฌด๊ด€์— ์ตœ๋Œ€ ์ฒ˜๋ฆฌ๋Ÿ‰์ด
ํ•„์š”ํ•˜๋ฉด unordered_map. ๊ฒŒ์ž„ ์—”์ง„ ๊ฐ™์€ ํ™˜๊ฒฝ์—์„œ๋Š” ๊ฑฐ์˜ ํ•ญ์ƒ
unordered_map ์ž…๋‹ˆ๋‹ค.

๋˜ ํ•˜๋‚˜ ์ค‘์š”ํ•œ ์ฐจ์ด๊ฐ€ iterator ๋ฌดํšจํ™”์ž…๋‹ˆ๋‹ค. unordered_map ์€ rehash
์‹œ ๋ชจ๋“  iteratorยทํฌ์ธํ„ฐยท์ฐธ์กฐ๊ฐ€ ๋ฌดํšจํ™”๋˜๋Š”๋ฐ, ์ด๊ฒŒ vector ์žฌํ• ๋‹น๊ณผ
๊ฐ™์€ ํŒจํ„ด์ž…๋‹ˆ๋‹ค. map ์€ ๋…ธ๋“œ ์•ˆ์ •์„ฑ์ด ๊ฐ•ํ•ด์„œ ์‚ฝ์ž…์€ ๋ฌดํšจํ™”๊ฐ€ ์ „ํ˜€
์—†๊ณ  ์‚ญ์ œ๋„ ์‚ญ์ œ๋œ ๋…ธ๋“œ๋งŒ ๋ฌดํšจํ™”๋ฉ๋‹ˆ๋‹ค โ€” list ์™€ ๊ฐ™์€ ๊ฐ•์ ์ž…๋‹ˆ๋‹ค.

[4] operator[] ํ•จ์ •๊ณผ C++17 ๊ฐœ์„ .

operator[] ๋Š” ํ‚ค๊ฐ€ ์—†์œผ๋ฉด default ๊ฐ’์„ ์ž๋™ ์‚ฝ์ž…ํ•˜๋Š” mutating
์—ฐ์‚ฐ์ด๋ผ const map ์—์„œ๋Š” ์ปดํŒŒ์ผ ์—๋Ÿฌ๊ฐ€ ๋‚ฉ๋‹ˆ๋‹ค. ๋˜ ๋ฌด๋ธŒ-์˜จ๋ฆฌ ํƒ€์ž…์—์„œ
"์žˆ์œผ๋ฉด ๊ทธ๋Œ€๋กœ ๋‘๊ณ  ์—†์„ ๋•Œ๋งŒ ์‚ฝ์ž…" ๊ฐ™์€ ์˜๋„๋ฅผ ํ‘œํ˜„ํ•˜๊ธฐ ๊นŒ๋‹ค๋กญ์Šต๋‹ˆ๋‹ค.

C++17 ์˜ try_emplace ์™€ insert_or_assign ์ด ์ด ๋ฌธ์ œ๋ฅผ ํ•ด๊ฒฐํ•ฉ๋‹ˆ๋‹ค.
try_emplace ๋Š” ํ‚ค๊ฐ€ ์ด๋ฏธ ์žˆ์œผ๋ฉด ์ธ์ž์กฐ์ฐจ ๋งŒ๋“ค์ง€ ์•Š์•„ unique_ptr
๊ฐ™์€ ๋ฌด๋ธŒ-์˜จ๋ฆฌ ํƒ€์ž…์—์„œ ์•ˆ์ „ํ•ฉ๋‹ˆ๋‹ค. insert_or_assign ์€ "์žˆ์œผ๋ฉด ๋Œ€์ž…,
์—†์œผ๋ฉด ์‚ฝ์ž…" ์˜๋„๋ฅผ ๋ช…ํ™•ํžˆ ํ‘œํ˜„ํ•ฉ๋‹ˆ๋‹ค.

[5] ์–ธ๋ฆฌ์–ผ.

์–ธ๋ฆฌ์–ผ์˜ TMap ์€ std::unordered_map ์— ๊ฐ€๊นŒ์šด ํ•ด์‹œ ๊ธฐ๋ฐ˜์ž…๋‹ˆ๋‹ค.
std::map ์— ์ง์ ‘ ๋Œ€์‘ํ•˜๋Š” RB-Tree ์ปจํ…Œ์ด๋„ˆ๋Š” 1๊ธ‰์œผ๋กœ ๋‘์ง€ ์•Š์•˜๊ณ ,
์ •๋ ฌ์ด ํ•„์š”ํ•˜๋ฉด TSortedMap ์„ ์“ฐ๋Š”๋ฐ, ์ด๊ฒƒ๋„ RB-Tree ๊ฐ€ ์•„๋‹Œ ์ •๋ ฌ๋œ
TArray ๊ธฐ๋ฐ˜์ž…๋‹ˆ๋‹ค.

์ด์œ ๋Š” 13๋ฒˆ์—์„œ ๋ณธ vector vs list ์™€ ๊ฐ™์€ ์บ์‹œ ์นœํ™” ์ฒ ํ•™์ž…๋‹ˆ๋‹ค.
๊ฒŒ์ž„ ์—”์ง„์€ ๋งค ํ”„๋ ˆ์ž„ ์ˆ˜๋งŒ ๊ฐ์ฒด๋ฅผ ์ˆœํšŒํ•˜๋ฏ€๋กœ ํŠธ๋ฆฌ ๋…ธ๋“œ ๋ถ„์‚ฐ๋ณด๋‹ค
์—ฐ์† ๋ฐฐ์—ด + ์ด์ง„ ํƒ์ƒ‰์ด ์บ์‹œ์ƒ ๋” ๋น ๋ฅผ ๋•Œ๊ฐ€ ๋งŽ์•„์„œ, 1๊ธ‰ ์‹œ๋ฏผ์€
TArray (vector) + TMapยทTSet (ํ•ด์‹œ) ๋งŒ ๋‘๊ณ  ํŠธ๋ฆฌ ์ปจํ…Œ์ด๋„ˆ๋Š”
๋ณด์กฐ์ ์œผ๋กœ๋งŒ ๋‘” ๊ฒ๋‹ˆ๋‹ค.

์š”์•ฝํ•˜๋ฉด โ€” map ์€ ์ •๋ ฌยท๋ฒ”์œ„ยท์ตœ์•… ๋ณด์žฅ์ด ํ•„์š”ํ•  ๋•Œ, unordered_map ์€
๋น ๋ฅธ ์กฐํšŒ๊ฐ€ ํ•„์š”ํ•  ๋•Œ, ๊ทธ๋ฆฌ๊ณ  ๊ฒŒ์ž„ ์—”์ง„์—์„œ๋Š” ์บ์‹œ ์นœํ™”์„ฑ์„ ์œ„ํ•ด
์–‘์ชฝ ๋‹ค ์‹ ์ค‘ํ•˜๊ฒŒ ์„ ํƒํ•ด์•ผ ํ•œ๋‹ค โ€” ๊ฐ€ 14๋ฒˆ์˜ ํ•ต์‹ฌ์ž…๋‹ˆ๋‹ค.

์ฐธ๊ณ 

  • 13_vector_vs_list.md โ€” ์‹œํ€€์Šค ์ปจํ…Œ์ด๋„ˆ์˜ ๋ฉ”๋ชจ๋ฆฌ ๋ ˆ์ด์•„์›ƒยทCPU ์บ์‹œ ๋ถ„์„. map ์˜ ๋…ธ๋“œ ์•ˆ์ •์„ฑ์€ list ์™€ ๋™์ผํ•œ ํŒจํ„ด, unordered_map rehash ๋ฌดํšจํ™”๋Š” vector ์žฌํ• ๋‹น๊ณผ ๋™์ผํ•œ ํŒจํ„ด
  • 11_smart_pointer.md โ€” map<Key, unique_ptr<T>> + try_emplace (C++17) ํŒจํ„ด. ๋ฌด๋ธŒ-์˜จ๋ฆฌ ํƒ€์ž…์„ ์—ฐ๊ด€ ์ปจํ…Œ์ด๋„ˆ์— ์•ˆ์ „ํ•˜๊ฒŒ ๋‹ด๊ธฐ
  • 12_prevent_copy.md โ€” Rule of Five, move-only ํƒ€์ž…. map ์€ ๋…ธ๋“œ ์•ˆ์ •์„ฑ์œผ๋กœ vector ๋งŒํผ noexcept move ์˜์กด๋„๊ฐ€ ๋‚ฎ์Œ
  • 10_pointer_deepdive.md โ€” unordered_map rehash ํ›„ ๋Œ•๊ธ€๋ง ํฌ์ธํ„ฐ (vector ์žฌํ• ๋‹น๊ณผ ๋™์ผ ํŒจํ„ด)
  • 09_rtti_raii.md โ€” map + ์Šค๋งˆํŠธ ํฌ์ธํ„ฐ ํ•ฉ์„ฑ RAII
  • 00_index.md โ€” CS ๋ฉด์ ‘ ์ธ๋ฑ์Šค
์ด ๊ธฐ์‚ฌ๋Š” ์ €์ž‘๊ถŒ์ž์˜ CC BY 4.0 ๋ผ์ด์„ผ์Šค๋ฅผ ๋”ฐ๋ฆ…๋‹ˆ๋‹ค.

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

Powered by Jekyll with Chirpy theme

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