๐ 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::map | RB-Tree ๊ธฐ๋ฐ ์ ๋ ฌ๋ ํค-๊ฐ ์ปจํ
์ด๋. ํค ์ค๋ณต ๋ถ๊ฐ |
| ย | std::set | RB-Tree ๊ธฐ๋ฐ ์ ๋ ฌ๋ ํค ์งํฉ. value ์์ |
| ย | std::multimap | ๋์ผ ํค ์ค๋ณต ํ์ฉ. equal_range ๋ก ๋ฒ์ ์กฐํ |
| ย | std::multiset | ๋์ผ ํค ์ค๋ณต ํ์ฉ set |
| ย | std::unordered_map | ํด์ ํ
์ด๋ธ ๊ธฐ๋ฐ. ํ๊ท O(1), ์์ ์์ |
| ย | std::unordered_set | ํด์ ํ
์ด๋ธ ๊ธฐ๋ฐ ํค ์งํฉ |
| ย | std::unordered_multimap / _multiset | ํด์ + ์ค๋ณต ํ์ฉ |
| ์๊ธฐ ๊ท ํ BST | Red-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 count | find ๋ iterator, count ๋ 0 ๋๋ 1 (multimap ์์๋ง ์๋ฏธ) |
| ย | emplace | in-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 | ํค ์ค๋ณต ํ์ฉ |
๋ชฉ์ฐจ
- ํต์ฌ ์์ฝ ์นด๋
- std::map ์ด๋ โ ์ ๋ ฌ๋ ์ฐ๊ด ์ปจํ
์ด๋
- ๋ด๋ถ ๋์ โ Red-Black Tree
- ์ฃผ์ ์ฐ์ฐ๊ณผ ์๊ฐ ๋ณต์ก๋
- iterator ๋ฌดํจํ ๊ท์น (vectorยทlist ์ ๋น๊ต)
- ์ ์ฌํ ๋ฒ์์ ๋ค๋ฅธ ์ปจํ
์ด๋ โ set / multimap / unordered_*
- ์ฝ๋ ์์ โ ๊ธฐ๋ณธ ์ฌ์ฉ / Custom Compare / emplace
- ๋ฉด์ ๋จ๊ณจ ๊ผฌ๋ฆฌ๋ฌผ๊ธฐ
- ์ธ๋ฆฌ์ผ
TMap vs STL - ํ๊ท ๋ค๋ฆฌ โ ๋ค๋ฅธ CS ํ์ผ ์ฐ๊ฒฐ
- ๊ผฌ๋ฆฌ์ง๋ฌธ ์์ ๊ฒฝ๋ก
- ๋ชจ์๋ฉด์ ๋ต๋ณ ํ
ํ๋ฆฟ (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์ด
| ์ฐ์ฐ | map | unordered_map |
|---|
| insert | O(log n) | ํ๊ท O(1), ์ต์
O(n) |
| erase | O(log n) | ํ๊ท O(1), ์ต์
O(n) |
| find | O(log n) | ํ๊ท O(1), ์ต์
O(n) |
| operator[] | O(log n) | ํ๊ท O(1) |
| ์ํ begin โ end | O(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 Tree | AVL 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. ์ปจํ
์ด๋๋ณ ๋น๊ตํ
| ย | vector | list | map | unordered_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) |
|---|
| ํค-๊ฐ + ์ค๋ณต X | std::map | std::unordered_map |
| ํค-๊ฐ + ์ค๋ณต O | std::multimap | std::unordered_multimap |
| ํค๋ง + ์ค๋ณต X | std::set | std::unordered_set |
| ํค๋ง + ์ค๋ณต O | std::multiset | std::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::map | std::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_map | TMap โ
1๊ธ ์๋ฏผ | open addressing |
| ์ ๋ ฌ ์
(RB-Tree) | std::set | (์์) โ TSortedSet? TArray::Sort | ย |
| ํด์ ์
| std::unordered_set | TSet โ
1๊ธ ์๋ฏผ | ย |
| ์ค๋ณต ํค ๋งต | std::multimap / unordered_multimap | TMultiMap | ย |
์ธ๋ฆฌ์ผ์ TArray(vector) + TMap(unordered_map) + TSet(unordered_set) ์ด 1๊ธ ์๋ฏผ์ด๊ณ , ํธ๋ฆฌ ๊ธฐ๋ฐ ์ ๋ ฌ ์ปจํ
์ด๋๋ ๋ณด์กฐ์ ์
๋๋ค โ 13๋ฒ์์ ๋ณธ std::list ์ฒ๋ผ โ์บ์ ์ ๋์ ์๋ฃ๊ตฌ์กฐ ํํผโ ์ฒ ํ์ด ์ผ๊ด๋ฉ๋๋ค.
9-6. TMap vs std::unordered_map ์ฐจ์ด์
| ย | std::unordered_map | TMap |
|---|
| ์ถฉ๋ ํด๊ฒฐ | 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 ๋ฉด์ ์ธ๋ฑ์ค