CS โ list sort
๐ 05/06 โ std::list::sort vs std::sort (์ ๋ฉค๋ฒ ํจ์๊ฐ ๋ฐ๋ก ์๋๊ฐ)
๋ชจ์๋ฉด์ ์ฃผ์ : โstd::list::sort()๊ฐ std::sort() ๋์ ๋ฐ๋ก ์กด์ฌํ๋ ์ด์ ์ ๋ํด์ ์ค๋ช ํด ์ฃผ์ธ์โ iterator ์นดํ ๊ณ ๋ฆฌ โ ์๊ณ ๋ฆฌ์ฆ ์ ํ โ ๋ ธ๋ ์ฌ์ฐ๊ฒฐ vs ๋ฐ์ดํฐ ์ด๋ โ stable ์ฌ๋ถ โ forward_listยทset/map::find ํจํด๊น์ง
ํ์ต ์์ญ ์ ํ์ โ ์๊ณ ๋ฆฌ์ฆ๊ณผ ์๋ฃ๊ตฌ์กฐ์ ๊ฒฐํฉ
17๋ฒ์์ std::find vs std::binary_search๋ก ์๊ณ ๋ฆฌ์ฆ ํจ์์ ๋ถ์
์ค๊ณ๋ฅผ ๋ดค๋ค๋ฉด, 18๋ฒ์ ์๊ณ ๋ฆฌ์ฆ๊ณผ ์๋ฃ๊ตฌ์กฐ๊ฐ ๋ง๋๋ ์ง์ ์
๋๋ค. std::sort๋ RandomAccessIterator๋ฅผ ์๊ตฌํ๋ ์ผ๋ฐ ์๊ณ ๋ฆฌ์ฆ์ด๊ณ , std::list::sort๋ ์ฐ๊ฒฐ ๋ฆฌ์คํธ์ ํน์ฑ์ ๋ง์ถ ๋ฉค๋ฒ ํจ์์
๋๋ค.
1
2
3
4
17๋ฒ std::find vs binary_search โ ์๊ณ ๋ฆฌ์ฆ ํจ์ (์ ํ vs ์ด๋ถ)
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
18๋ฒ std::list::sort vs std::sort โ
โ ๋ฉค๋ฒ ํจ์ vs ์๊ณ ๋ฆฌ์ฆ (์ ๋ฐ๋ก?)
์ดํ custom comparator / partial_sort โ ์ ๋ ฌ family ํ์ฅ
์ด ์ฃผ์ ๋ 17๋ฒ์ 9-1 iterator ์นดํ
๊ณ ๋ฆฌ(InputIterator โ ForwardIterator โ BidirectionalIterator โ RandomAccessIterator)๋ฅผ ๊ทธ๋๋ก ์ด์ด๋ฐ์ต๋๋ค. ๊ทธ๋ฆฌ๊ณ set/map์์ ๋ฉค๋ฒ ํจ์ find()๋ฅผ ์จ์ผ ํ๋ ์ด์ (15๋ฒ~17๋ฒ์์ ๋ณธ ๊ทธ ์ปจ๋ฒค์
)์๋ ๊ฐ์ ๋งฅ๋ฝ์
๋๋ค โ ์๋ฃ๊ตฌ์กฐ์ ํน์ฑ์ ์๊ณ ๋ฆฌ์ฆ์ด ํ์ฉํ ์ ์์ ๋, ๋ฉค๋ฒ ํจ์๊ฐ ๋ฐ๋ก ์กด์ฌํ๋ค.
๋ชจ์๋ฉด์ ๋ต๋ณ
std::sort๋ <algorithm> ํค๋์ ์ผ๋ฐ ์ ๋ ฌ ์๊ณ ๋ฆฌ์ฆ์ด๊ณ , std::list::sort๋ std::list์ ๋ฉค๋ฒ ํจ์์
๋๋ค. ๋์ด ๋ฐ๋ก ์กด์ฌํ๋ ์ด์ ๋ ํฌ๊ฒ ์ธ ๊ฐ์ง์
๋๋ค.
์ฒซ์งธ, iterator ์นดํ
๊ณ ๋ฆฌ๊ฐ ๋ค๋ฆ
๋๋ค. std::sort๋ RandomAccessIterator๋ฅผ ์๊ตฌํฉ๋๋ค. ์ค๊ฐ์ it + n ๊ฐ์ ์ ํ๋ it[i] ์ธ๋ฑ์ฑ์ด ๊ฐ๋ฅํด์ผ quicksort์ partition์ด ๋์ํ๊ธฐ ๋๋ฌธ์
๋๋ค. ๊ทธ๋ฐ๋ฐ std::list::iterator๋ BidirectionalIterator๊น์ง๋ง ์ง์ํฉ๋๋ค โ ++it, --it์ ๋์ง๋ง it + n์ ์ ๋ฉ๋๋ค. ๊ทธ๋์ std::sort(list.begin(), list.end())๋ ์ปดํ์ผ ์๋ฌ๊ฐ ๋ฉ๋๋ค. ์ด๊ฒ ๊ฐ์ฅ ์ง์ ์ ์ธ ์ด์ ์
๋๋ค.
๋์งธ, ์ ๋ ฌ ์๊ณ ๋ฆฌ์ฆ ์์ฒด๊ฐ ๋ฌ๋ผ์ผ ํจ์จ์ ์
๋๋ค. std::sort๋ ๋ณดํต introsort๋ก ๊ตฌํ๋ฉ๋๋ค โ quicksort๋ก ์์ํด์ ์ฌ๊ท ๊น์ด๊ฐ ๊น์ด์ง๋ฉด heapsort๋ก ํด๋ฐฑํ๊ณ , ์์ ๊ตฌ๊ฐ์ insertion sort๋ก ๋ง๋ฌด๋ฆฌํ๋ ํ์ด๋ธ๋ฆฌ๋์
๋๋ค. ๋ฌด์์ ์ ๊ทผ์ผ๋ก partition์ ๋น ๋ฅด๊ฒ ์ฒ๋ฆฌํ ์ ์๋ค๋ ์ ์ ์์์ ๋์ํฉ๋๋ค. ๋ฐ๋ฉด std::list::sort๋ ๋ณํฉ ์ ๋ ฌ (merge sort) ๊ธฐ๋ฐ์
๋๋ค. ์ฐ๊ฒฐ ๋ฆฌ์คํธ๋ ํฌ์ธํฐ ์ฌ์ฐ๊ฒฐ๋ง์ผ๋ก ๋ ์ ๋ ฌ ๋ฆฌ์คํธ๋ฅผ ํฉ์น ์ ์๊ธฐ ๋๋ฌธ์ ๋ณํฉ ์ ๋ ฌ (merge sort)๊ฐ ์์ฐ์ค๋ฝ๊ณ , ๋ฐ์ดํฐ ์์ฒด๋ฅผ ์ฎ๊ธธ ํ์๊ฐ ์์ต๋๋ค.
์
์งธ, ๊ทธ ๊ฒฐ๊ณผ ๋น์ฉ ๊ตฌ์กฐ๊ฐ ์์ ํ ๋ฌ๋ผ์ง๋๋ค. ๋ ๋ค ์๊ฐ๋ณต์ก๋๋ O(n log n)์ด์ง๋ง, std::list::sort๋ ๋น๊ต ์ธ ๋ฐ์ดํฐ ์ด๋ ๋น์ฉ์ด 0์
๋๋ค โ ๋
ธ๋์ prev/next ํฌ์ธํฐ๋ง swapํ๋๊น์. std::sort๋ partition ๊ณผ์ ์์ ์์ ์์ฒด๋ฅผ swapํฉ๋๋ค. ํฐ ๊ฐ์ฒด๋ฅผ ๋ด์ ์ปจํ
์ด๋๋ผ๋ฉด ์ด ์ฐจ์ด๊ฐ ์ค์ธก ์ฑ๋ฅ์ ํฐ ์ํฅ์ ์ค๋๋ค. ๊ทธ๋ฆฌ๊ณ std::list::sort๋ stable sort์ด๊ณ ์ถ๊ฐ ๋ฉ๋ชจ๋ฆฌ๋ O(1)(in-place merge)์
๋๋ค.
์ด๊ฒ STL ์ ๋ฐ์ ์ผ๊ด๋ ์ค๊ณ์
๋๋ค. set์ด๋ map์์ std::find ๋์ ๋ฉค๋ฒ find()๋ฅผ ์ฐ๋ ์ด์ ์ ๋๊ฐ์ต๋๋ค โ ์๋ฃ๊ตฌ์กฐ์ ํน์ฑ์ ์๊ณ ๋ฆฌ์ฆ์ด ํ์ฉํ ์ ์์ ๋, ๋ฉค๋ฒ ํจ์๊ฐ ๋ฐ๋ก ์กด์ฌํฉ๋๋ค. forward_list::sort๋ ๊ฐ์ ์ด์ ๋ก ๋ฐ๋ก ์๊ณ , ์ด๋ฐ ํจํด์ด STL์ โ๋ฉค๋ฒ vs ์๊ณ ๋ฆฌ์ฆ ๋ถ์
โ ์ปจ๋ฒค์
์
๋๋ค.
ํต์ฌ ๊ฐ๋
| ๋ถ๋ฅ | ํค์๋ | ํ ์ค ์ ์ |
|---|---|---|
| ํจ์ ์ ์ | std::sort | <algorithm> ํค๋, RandomAccessIterator ์๊ตฌ, introsort |
| ย | std::list::sort | std::list ๋ฉค๋ฒ ํจ์, BidirectionalIterator๋ก OK, ๋ณํฉ ์ ๋ ฌ (merge sort) |
| ย | std::forward_list::sort | std::forward_list ๋ฉค๋ฒ ํจ์, ForwardIterator๋ก OK, ๋ณํฉ ์ ๋ ฌ (merge sort) |
| iterator ์นดํ ๊ณ ๋ฆฌ | RandomAccessIterator | it + n, it[i] ๊ฐ๋ฅ (vectorยทdequeยทarray) |
| ย | BidirectionalIterator | ++it, --it๋ง ๊ฐ๋ฅ (listยทsetยทmap) |
| ย | ForwardIterator | ++it๋ง ๊ฐ๋ฅ (forward_list) |
| ์ ๋ ฌ ์๊ณ ๋ฆฌ์ฆ | introsort | quicksort + heapsort + insertion sort ํ์ด๋ธ๋ฆฌ๋. std::sort ๊ตฌํ |
| ย | ๋ณํฉ ์ ๋ ฌ (merge sort) | ๋ ์ ๋ ฌ ๋ฆฌ์คํธ๋ฅผ ๋ณํฉ. list::sort ๊ธฐ๋ฐ โ ํฌ์ธํฐ ์ฌ์ฐ๊ฒฐ๋ง |
| ย | partition (quicksort) | pivot ๊ธฐ์ค ์ข/์ฐ ๋ถํ . ๋ฌด์์ ์ ๊ทผ ํ์ |
| ์๊ฐ๋ณต์ก๋ | O(n log n) | ๋ ๋ค ๋์ผ. ์ด๋ก ๊ฐ์ ๊ฐ์ |
| ย | ๋ฐ์ดํฐ ์ด๋ ๋น์ฉ | std::sort โ swap ๋ค์ / list::sort โ 0 (ํฌ์ธํฐ๋ง) |
| ์์ ์ฑ | stable sort | ๋๋ฑ ์์์ ์๋ ์์ ์ ์ง. list::sort๋ stable |
| ย | unstable | std::sort๋ ๋น์์ . ์์ ์ฑ ํ์ํ๋ฉด std::stable_sort |
| ์ถ๊ฐ ๋ฉ๋ชจ๋ฆฌ | O(1) in-place | list::sort๋ ๋
ธ๋ ์ฌ์ฐ๊ฒฐ๋ง โ ์ถ๊ฐ ํ ๋น X |
| ย | O(log n) ์คํ | std::sort (์ฌ๊ท ๊น์ด) |
| ๋น๊ต ํจ์ | strict weak ordering | ๋ ๋ค < ๋๋ ์ฌ์ฉ์ ๋น๊ต์ ์๊ตฌ |
| ์ปดํ์ผ ์๋ฌ | std::sort(list) ์๋ | error: no match for 'operator-' ๋ฑ โ RandomAccess ๋ถ์ฌ |
| ๊ด๋ จ ์๊ณ ๋ฆฌ์ฆ | std::stable_sort | ์์ ์ ๋ ฌ. ์ถ๊ฐ ๋ฉ๋ชจ๋ฆฌ O(n) ๋๋ O(n logยฒ n) |
| ย | std::partial_sort | ์์ k๊ฐ๋ง ์ ๋ ฌ. heap ๊ธฐ๋ฐ O(n log k) |
| ย | std::nth_element | k๋ฒ์งธ ์์๋ง ์ ์๋ฆฌ์. O(n) ํ๊ท |
| ๋ฉค๋ฒ vs ์๊ณ ๋ฆฌ์ฆ | set/map::find | ํธ๋ฆฌ O(log n) โ ์๊ณ ๋ฆฌ์ฆ std::find๋ O(n)์ด๋ผ ์ํด |
| ย | unordered_map::find | ํด์ O(1) ํ๊ท |
| ย | list::sort | ๋
ธ๋ ์ฌ์ฐ๊ฒฐ๋ก O(n log n) โ ์๊ณ ๋ฆฌ์ฆ์ ์ปดํ์ผ X |
| ย | forward_list::sort | ๋จ๋ฐฉํฅ์ด๋ผ ๋๋์ฑ ์๊ณ ๋ฆฌ์ฆ ๋ถ๊ฐ |
| ์ธ๋ฆฌ์ผ | Algo::Sort | std::sort ๋์. TArray ๋ฑ RandomAccess ์ปจํ
์ด๋์ฉ |
| ย | TArray::Sort | ๋ฉค๋ฒ ํจ์. introsort ๊ธฐ๋ฐ |
| ย | TArray::StableSort | ์์ ์ ๋ ฌ ๋ฉค๋ฒ ํจ์ |
| ย | TLinkedList | ํฌํผ ์์ค. ์ ๋ ฌ ๋ฉค๋ฒ ํจ์๋ ๋ฐ๋ก ์์ (์๋ ๊ตฌํ ํ์) |
๋ชฉ์ฐจ
- ํต์ฌ ์์ฝ ์นด๋
- ์ปดํ์ผ ์๋ฌ๋ถํฐ โ ์ std::sort(list)๋ ์ ๋๋
- iterator ์นดํ ๊ณ ๋ฆฌ ๋ณต๊ธฐ โ 17๋ฒ 9-1๊ณผ์ ์ฐ๊ฒฐ
- ์ ๋ ฌ ์๊ณ ๋ฆฌ์ฆ ์ฐจ์ด โ introsort vs ๋ณํฉ ์ ๋ ฌ (merge sort)
- ๋ ธ๋ ์ฌ์ฐ๊ฒฐ โ ๋ฐ์ดํฐ ์ด๋ ๋น์ฉ 0์ ์๋ฏธ
- stable ์ฌ๋ถ / ์ถ๊ฐ ๋ฉ๋ชจ๋ฆฌ ๋น๊ต
- forward_list::sort โ ๊ฐ์ ์ด์ ๋ก ๋ ๋ฐ๋ก
- ๋ฉค๋ฒ vs ์๊ณ ๋ฆฌ์ฆ ์ปจ๋ฒค์ โ set/map::find์ ๊ฐ์ ํจํด
- ๊ด๋ จ ์ ๋ ฌ family โ stable_sort / partial_sort / nth_element
- ์ธ๋ฆฌ์ผ์์์ ์ ๋ ฌ โ Algo::Sort / TArray::Sort / TLinkedList
- ๊ผฌ๋ฆฌ์ง๋ฌธ ์์ ๊ฒฝ๋ก
1. ํต์ฌ ์์ฝ ์นด๋
30์ด ๋ต๋ณ
1
2
3
4
5
6
7
8
9
10
std::sort = <algorithm>, RandomAccessIterator ์๊ตฌ, introsort, unstable, swap
std::list::sort = list ๋ฉค๋ฒ ํจ์, BidirectionalIterator๋ก OK, ๋ณํฉ ์ ๋ ฌ (merge sort), stable, ํฌ์ธํฐ ์ฌ์ฐ๊ฒฐ
์ด์ 3๊ฐ์ง:
โ iterator ์นดํ
๊ณ ๋ฆฌ ์ฐจ์ด โ list::iterator๋ RandomAccess ์๋ โ ์ปดํ์ผ ์๋ฌ
โก ์๊ณ ๋ฆฌ์ฆ์ด ๋ค๋ฆ โ quicksort partition์ ๋ฌด์์ ์ ๊ทผ ํ์, list์ ๋ณํฉ ์ ๋ ฌ (merge sort)๊ฐ ์ต์
โข ๋น์ฉ ๊ตฌ์กฐ โ list::sort๋ ๋
ธ๋ ํฌ์ธํฐ๋ง ์ฌ์ฐ๊ฒฐ, ๋ฐ์ดํฐ ์ด๋ 0
๊ฐ์ ํจํด: set/map::find vs std::find, forward_list::sort
โ "์๋ฃ๊ตฌ์กฐ ํน์ฑ์ ์๊ณ ๋ฆฌ์ฆ์ด ๋ชป ์ด๋ฆด ๋ ๋ฉค๋ฒ ํจ์๊ฐ ๋ฐ๋ก ์กด์ฌํ๋ค"
๊ผฌ๋ฆฌ์ง๋ฌธ ์ฐ๊ฒฐ ๋งต
1
2
3
4
5
6
7
8
9
10
11
12
std::list::sort vs std::sort
โโโ ์ std::sort(list)๋ ์ปดํ์ผ ์๋ฌ? โ list iterator๋ BidirectionalIterator
โ โโโ 17๋ฒ 9-1 iterator ์นดํ
๊ณ ๋ฆฌ (Random Access ํ์)
โโโ ์ list์ ๋ณํฉ ์ ๋ ฌ (merge sort)๊ฐ ์ต์ ? โ ํฌ์ธํฐ ์ฌ์ฐ๊ฒฐ๋ก in-place merge๊ฐ ์์ฐ์ค๋ฌ์
โ โโโ quicksort partition์ ๋ฌด์์ ์ ๊ทผ ํ์
โโโ ๋ ๋ค O(n log n)์ธ๋ฐ ๋ญ๊ฐ ๋ค๋ฆ? โ ๋ฐ์ดํฐ ์ด๋ ๋น์ฉ (swap vs ํฌ์ธํฐ)
โโโ stable ์ฌ๋ถ? โ list::sort๋ stable / std::sort๋ unstable
โ โโโ ์์ ์ ๋ ฌ ํ์ํ๋ฉด std::stable_sort
โโโ forward_list๋? โ forward_list::sort ๋ฐ๋ก ์กด์ฌ (ForwardIterator๋ผ ๋ ์ ํ์ )
โโโ ๊ฐ์ ํจํด? โ set/map::find, unordered_map::find (๋ฉค๋ฒ vs ์๊ณ ๋ฆฌ์ฆ ์ปจ๋ฒค์
)
โโโ ์ ๋ ฌ family โ stable_sort / partial_sort / nth_element
โโโ 13๋ฒ vector vs list, 16๋ฒ STL ์ปจํ
์ด๋ ์ ๋ฆฌ๋ก ํ๊ท
2. ์ปดํ์ผ ์๋ฌ๋ถํฐ โ ์ std::sort(list)๋ ์ ๋๋
ํต์ฌ ํ ๋ฌธ์ฅ
std::sort๋ RandomAccessIterator๋ฅผ ์๊ตฌํ๋๋ฐstd::list::iterator๋ BidirectionalIterator๋ผ์, ์ปดํ์ผ ๋จ๊ณ์์ ๊ฑฐ๋ถ๋ฉ๋๋ค.
์๋ํ๋ฉด ์ด๋ป๊ฒ ๋๋
1
2
3
4
5
6
7
8
9
10
11
12
13
14
#include <algorithm>
#include <list>
int main() {
std::list<int> lst = {3, 1, 4, 1, 5, 9, 2, 6};
std::sort(lst.begin(), lst.end()); // โ
์ปดํ์ผ ์๋ฌ
// GCC ๋ฉ์์ง (์์ง):
// error: no match for 'operator-' (operand types are
// 'std::_List_iterator<int>' and 'std::_List_iterator<int>')
//
// โ std::sort ๋ด๋ถ์์ (last - first)๋ก ๊ฑฐ๋ฆฌ ๊ณ์ฐ์ ์๋ํ๋๋ฐ,
// list iterator๋ - ์ฐ์ฐ์๊ฐ ์ ์๋ผ ์์ง ์์.
}
โ std::sort ๊ตฌํ ์ด๋์ ๊ฐ mid = first + (last - first) / 2 ๊ฐ์ ๋ฌด์์ ์ ํ๋ฅผ ํฉ๋๋ค. list iterator๋ ๊ทธ ์ฐ์ฐ์ ์ง์ํ์ง ์์ผ๋ฏ๋ก ํ
ํ๋ฆฟ ์ธ์คํด์คํ ๋จ๊ณ์์ ์คํจํฉ๋๋ค.
์ ๋ต โ ๋ฉค๋ฒ ํจ์ ์ฌ์ฉ
1
2
3
4
std::list<int> lst = {3, 1, 4, 1, 5, 9, 2, 6};
lst.sort(); // โ
OK โ ์ค๋ฆ์ฐจ์
lst.sort(std::greater<int>()); // ๋ด๋ฆผ์ฐจ์ (๋น๊ต์)
lst.sort([](int a, int b){ return a > b; }); // ๋๋ค๋ ๊ฐ๋ฅ
โ ์ธ์ ์์ด ํธ์ถํ๋ฉด < ๊ธฐ๋ณธ, ๋น๊ต์ ์ธ์๋ก strict weak ordering์ ๋ง์กฑํ๋ ํจ์ ๊ฐ์ฒด๋ฅผ ๋ฐ์ ์ ์์ต๋๋ค.
๊ฐ์ ํจ์๋ช ์ ๋ค๋ฅธ ์ผ์ด์ค โ vector / deque / array
1
2
3
4
5
6
7
8
9
std::vector<int> v = {3, 1, 4, 1, 5, 9, 2, 6};
std::sort(v.begin(), v.end()); // OK โ RandomAccessIterator
// vector์๋ ๋ฉค๋ฒ sort()๊ฐ ์์ โ ์๊ณ ๋ฆฌ์ฆ์ผ๋ก ์ถฉ๋ถํ๋๊น
std::deque<int> dq = {3, 1, 4};
std::sort(dq.begin(), dq.end()); // OK โ deque๋ RandomAccess
std::array<int, 4> ar = {3, 1, 4, 1};
std::sort(ar.begin(), ar.end()); // OK
โ RandomAccess๋ฅผ ์ง์ํ๋ ์ปจํ ์ด๋์๋ ๋ฉค๋ฒ sort๊ฐ ์๊ณ , ๊ทธ๋ ์ง ์์ list/forward_list์๋ง ๋ฉค๋ฒ sort๊ฐ ๋ฐ๋ก ์๋ค๋ ๋น๋์นญ์ด ํต์ฌ์ ๋๋ค. ์๊ณ ๋ฆฌ์ฆ ํจ์๋ก ์ถฉ๋ถํ๋ฉด ๋ฉค๋ฒ๋ฅผ ์ ๋ง๋๋ ๊ฒ STL ์ปจ๋ฒค์ ์ ๋๋ค.
3. iterator ์นดํ ๊ณ ๋ฆฌ ๋ณต๊ธฐ โ 17๋ฒ 9-1๊ณผ์ ์ฐ๊ฒฐ
ํต์ฌ ํ ๋ฌธ์ฅ
17๋ฒ์์ ์ ๋ฆฌํ iterator ์นดํ ๊ณ ๋ฆฌ(Input โ Forward โ Bidirectional โ RandomAccess)๊ฐ ๊ทธ๋๋ก ์ ๋ ฌ ์๊ณ ๋ฆฌ์ฆ ์ ํ์ ๊ฒฐ์ ํฉ๋๋ค โ list๊ฐ ํ ๋จ๊ณ ๋ถ์กฑํ๋ค๋ ์ฌ์ค์ด ๋ชจ๋ ์ฐจ์ด์ ์ถ๋ฐ์ ์ ๋๋ค.
์นดํ ๊ณ ๋ฆฌ ํ (17๋ฒ 9-1 ์ฌํ์ฉ)
| ์นดํ ๊ณ ๋ฆฌ | ๊ฐ๋ฅ ์ฐ์ฐ | ๋ํ ์ปจํ ์ด๋ | sort ๊ฐ๋ฅ? |
|---|---|---|---|
| Input | ++it, *it(์ฝ๊ธฐ 1ํ) | istream_iterator | X |
| Forward | + ์ฌ๋ฌ ๋ฒ ์ฝ๊ธฐ | forward_list | ๋ฉค๋ฒ sort() ๋ง |
| Bidirectional | + --it ์ญ๋ฐฉํฅ | list, set, map | ๋ฉค๋ฒ sort() (list๋ง) |
| RandomAccess | + it + n, it[n], it < it2 | vector, deque, array | std::sort OK |
BidirectionalIterator ์์ธํ โ โํ ์นธ์ฉ ์ยท๋คโ๋ง ๊ฐ๋ฅํ๋ค๋ ์๋ฏธ
โ
list::iterator๋ BidirectionalIterator๋คโ๋ผ๋ ๋ง์ ์ยท๋ค ์๋ฐฉํฅ์ผ๋ก ํ ์นธ์ฉ๋ง ์ด๋ํ ์ ์๋ค๋ ๋ป์ ๋๋ค. ์ ํ(it+5)๋ ๊ฑฐ๋ฆฌ ๊ณ์ฐ(it2-it1)์ ์ ๋ฉ๋๋ค.
์ง์ยท๋น์ง์ ์ฐ์ฐ
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
std::list<int> lst = {1, 2, 3, 4, 5};
auto it = lst.begin();
// โ
๊ฐ๋ฅ (Bidirectional ๋ณด์ฅ)
++it; // ์์ผ๋ก 1์นธ O(1)
--it; // ๋ค๋ก 1์นธ O(1) โ Forward์ ๋ค๋ฅธ ์
*it; // ์ญ์ฐธ์กฐ ์ฝ๊ธฐ/์ฐ๊ธฐ
it == it2; // ๋๋ฑ ๋น๊ต
it != it2; // ๋น๋๋ฑ ๋น๊ต
// โ ๋ถ๊ฐ๋ฅ (RandomAccess๋ง ๊ฐ๋ฅ)
it + 5; // ์ปดํ์ผ ์๋ฌ โ ์ ํ
it - it2; // ์ปดํ์ผ ์๋ฌ โ ๊ฑฐ๋ฆฌ ๊ณ์ฐ
it[3]; // ์ปดํ์ผ ์๋ฌ โ ์ธ๋ฑ์ฑ
it < it2; // ์ปดํ์ผ ์๋ฌ โ ์์ ๋น๊ต
โ์โ ์๋ฐฉํฅ๊น์ง๋ง ๊ฐ๋ฅํ๊ฐ โ list ๋ ธ๋ ๊ตฌ์กฐ ๋๋ฌธ
1
2
3
4
5
list ๋
ธ๋: [prev | data | next] โโ [prev | data | next] โโ ...
++it โ ํ์ฌ ๋
ธ๋์ next ๋ฐ๋ผ๊ฐ๊ธฐ O(1) (ํฌ์ธํฐ ํ ๋ฒ)
--it โ ํ์ฌ ๋
ธ๋์ prev ๋ฐ๋ผ๊ฐ๊ธฐ O(1) (Bidirectional์ ํต์ฌ โ Forward์ ์๋ ๋ฅ๋ ฅ)
it+5 โ next๋ฅผ 5๋ฒ ๋ฐ๋ผ๊ฐ์ผ ํจ O(n) โ STL์ด ์๋์ ์ผ๋ก ๋ง์
โ ๋
ธ๋๋ ๋ฉ๋ชจ๋ฆฌ์ ๋ถ์ฐ๋์ด ์์ด์ 5๋ฒ์งธ ๋
ธ๋์ ์ฃผ์๋ฅผ ํ ๋ฒ์ ๊ณ์ฐํ ์๊ฐ ์์ต๋๋ค. ๋ฌด์์ ์ ๊ทผ์ ํ๋ด๋ด๋ ค๋ฉด next๋ฅผ 5๋ฒ ๋ฐ๋ผ๊ฐ์ผ ํ๊ณ ๊ทธ๊ฑด O(n)์
๋๋ค. STL์ โ๋๋ฆฐ ์ฐ์ฐ์ ์์ ํํํ ์ ์๊ฒ ํ๋ผโ๋ ์ฒ ํ์ด๋ผ ์ปดํ์ผ ๋จ๊ณ์์ ๋ง์ต๋๋ค.
์นดํ ๊ณ ๋ฆฌ ๊ณ์ธต โ ์์๋ ํ์์ ๋ชจ๋ ๋ฅ๋ ฅ์ ํฌํจ
1
2
3
4
5
6
RandomAccess โ Bidirectional โ Forward โ Input
RandomAccess โ ++ -- it+n it[n] *it ๋ค ๊ฐ๋ฅ
Bidirectional โ ++ -- *it (it+n ์์)
Forward โ ++ *it (-- ๋ ์์)
Input โ ++ *it (1ํ ์ฝ๊ธฐ๋ง)
โ Bidirectional์ด Forward์ ์์์ด๋ฏ๋ก, ForwardIterator๋ฅผ ์๊ตฌํ๋ ์๊ณ ๋ฆฌ์ฆ(std::find, std::count ๋ฑ)์ list iterator๋ก๋ ๋์ํฉ๋๋ค. ๋ฐ๋๋ก RandomAccess๋ฅผ ์๊ตฌํ๋ std::sort๋ list iterator๋ก ์ ๋ฉ๋๋ค.
์ RandomAccess๊ฐ ํ์ํ๊ฐ โ quicksort ์๊ฐ
quicksort์ ํต์ฌ์ partition์ ๋๋ค.
1
2
3
4
5
6
7
8
9
10
[3, 1, 4, 1, 5, 9, 2, 6]
pivot = 4
โ
์ข(< 4) | ์ฐ(โฅ 4) ๋ก ๋ถํ
[3, 1, 1, 2] | [4, 5, 9, 6]
๋ถํ ๊ณผ์ :
โ pivot ์ ํ โ ๋ณดํต mid = first + (last-first)/2 โ ๋ฌด์์ ์ ๊ทผ
โก ์ ๋์์ ์์ํด left++, right-- ํ๋ฉฐ swap โ --it๋ ํ์
โข ์ฌ๊ท ํธ์ถ ์ leftยทright ๋ถ๋ถ ๊ตฌ๊ฐ ์ธ๋ฑ์ฑ โ it + n
โ list iterator๋ก๋ โก ์ ์ ๋์์ ๋ง๋๊ธฐ๊น์ง์ ๊ฑฐ๋ฆฌ ๊ณ์ฐ์ด O(n)์ด๊ณ , โ ์ mid ์ ํ๋ O(n)์ด์ด์ ์ด๋ก ์๊ฐ๋ณต์ก๋๋ถํฐ ๊นจ์ง๋๋ค. ๊ทธ๋์ quicksort๋ list์ ๋ถ์ ํฉ.
partition ๊ณผ์ ์์ธํ โ quicksort์ ์ฌ์ฅ
partition์ โpivot ๊ธฐ์ค์ผ๋ก ์ข์ฐ๋ฅผ ๋๋๋ ํ ๋จ๊ณโ์ ๋๋ค. quicksort ์ ์ฒด ๋น์ฉ์ ๋๋ถ๋ถ์ด partition์์ ๋ฐ์ํ๊ณ , ์์ ์ฑยท์๊ฐ๋ณต์ก๋๊ฐ ๋ชจ๋ partition ๋ฐฉ์์ ์ข์ฐ๋ฉ๋๋ค.
Lomuto partition (๋จ์ํ ๋ฒ์ , ๊ต๊ณผ์์ฉ)
1
2
3
4
5
6
7
8
9
10
11
12
int partition(arr, lo, hi) {
int pivot = arr[hi]; // ๋ณดํต ๋ง์ง๋ง ์์๋ฅผ pivot์ผ๋ก
int i = lo - 1; // i: 'pivot๋ณด๋ค ์์ ์์๋ค์ ๋'
for (int j = lo; j < hi; ++j) {
if (arr[j] < pivot) {
++i;
swap(arr[i], arr[j]);
}
}
swap(arr[i+1], arr[hi]); // pivot์ ๊ฐ์ด๋ฐ๋ก
return i + 1; // pivot์ ์ต์ข
์์น
}
์๊ฐํ:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
์ด๊ธฐ: [3, 1, 4, 1, 5, 9, 2, 6] pivot = 6 (๋ง์ง๋ง)
i = -1, j = 0
j=0: 3<6 โ i=0, swap(a[0],a[0]) [3, 1, 4, 1, 5, 9, 2, 6]
j=1: 1<6 โ i=1, swap(a[1],a[1]) [3, 1, 4, 1, 5, 9, 2, 6]
j=2: 4<6 โ i=2, swap(a[2],a[2]) [3, 1, 4, 1, 5, 9, 2, 6]
j=3: 1<6 โ i=3, swap(a[3],a[3]) [3, 1, 4, 1, 5, 9, 2, 6]
j=4: 5<6 โ i=4, swap(a[4],a[4]) [3, 1, 4, 1, 5, 9, 2, 6]
j=5: 9<6 โ ์๋์ค (i ๊ทธ๋๋ก)
j=6: 2<6 โ i=5, swap(a[5],a[6]) [3, 1, 4, 1, 5, 2, 9, 6]
๋ง์ง๋ง swap(a[6],a[7]): [3, 1, 4, 1, 5, 2, 6, 9]
โ pivot ์๋ฆฌ ํ์
์ข์ธก [3, 1, 4, 1, 5, 2] (๋ชจ๋ < 6) | ์ฐ์ธก [9] (> 6)
โ partition ํ ๋ฒ์ด๋ฉด pivot์ ์ต์ข ์์น๊ฐ ํ์ ๋๊ณ , ์ขยท์ฐ๋ ๋ ๋ฆฝ์ ์ผ๋ก ์ ๋ ฌํ๋ฉด ๋ฉ๋๋ค (์ฌ๊ท).
Hoare partition (์ค์ introsort๊ฐ ์ฐ๋ ๋ฒ์ )
1
2
3
4
5
6
7
์ ๋์์ ์์ํด ์์ชฝ์ผ๋ก ์ขํ์ค๋ฉฐ swap.
์ข์ธก ์ธ๋ฑ์ค โ: pivot๋ณด๋ค ํฐ ๊ฒ ๋ง๋ ๋๊น์ง
์ฐ์ธก ์ธ๋ฑ์ค โ: pivot๋ณด๋ค ์์ ๊ฒ ๋ง๋ ๋๊น์ง
๋์ด ๋ง๋๋ฉด ์ข
๋ฃ, ๋ ๊ตฌ๊ฐ์ ์ฌ๊ท.
์ฅ์ : swap ํ์๊ฐ Lomuto์ ์ฝ 1/3
๋จ์ : pivot์ด ์ ํํ ์๋ฆฌ์ ์ ๊ฐ๊ณ partition ๊ฒฝ๊ณ๋ง ๋ฐํ (๊ทธ๋๋ ์ ๋ ฌ์ ๋จ)
pivot ์ ํ โ median-of-three
1
2
3
4
5
6
๋์ pivot โ quicksort๊ฐ O(nยฒ)๋ก ๋จ์ด์ง
(์: ์ด๋ฏธ ์ ๋ ฌ๋ ์
๋ ฅ + '์ฒซ ์์'๋ฅผ pivot์ผ๋ก ์ก๋ ๋ฐฉ์)
introsort์ ๋ฐฉ์ด ์ฅ์น:
โ median-of-three: ์ฒซยท์ค๊ฐยท๋ ์ธ ์์ ์ค ์ค๊ฐ๊ฐ์ pivot์ผ๋ก
โก ์ฌ๊ท ๊น์ด 2*logโ(n) ์ด๊ณผ ์ heapsort ํด๋ฐฑ โ ์ต์
๋ O(n log n) ๋ณด์ฅ
์ partition์ RandomAccess๊ฐ ํ์์ธ๊ฐ โ ํ ๋ฒ ๋ ์ ๋ฆฌ
1
2
3
4
5
6
7
์ค๊ฐ๊ฐ ์ ํ: mid = first + (last - first) / 2 โ it + n
์ ๋ swap: swap(*lo, *hi--), ++lo โ ์๋ฐฉํฅ + ์ธ๋ฑ์ค
์ฌ๊ท ํธ์ถ: partition(arr, lo, mid-1) โ ๋ถ๋ถ ๊ตฌ๊ฐ ์ธ๋ฑ์ฑ
์ด ์ฐ์ฐ๋ค์ด ๋ชจ๋ O(1)์ด์ด์ผ partition ํ ๋ฒ์ด O(n)์ผ๋ก ๋๋จ.
list iterator๋ it+n์ด O(n) โ partition ํ ๋ฒ์ด O(nยฒ) โ quicksort ์์ฒด๊ฐ O(nยณ)
โ ๊ทธ๋์ list์ quicksort/introsort ์์ฒด๊ฐ ๋ถ์ ํฉ.
์ ๋ณํฉ ์ ๋ ฌ (merge sort)๊ฐ list์ ์ต์ ์ธ๊ฐ โ ์ง๊ด
๋ณํฉ ์ ๋ ฌ (merge sort)์ ๋ ์ ๋ ฌ ๋ฆฌ์คํธ ๋ณํฉ(merge) ๋จ๊ณ๋:
1
2
3
4
5
6
7
A: 1 โ 3 โ 5
B: 2 โ 4 โ 6
โ merge
๊ฒฐ๊ณผ: 1 โ 2 โ 3 โ 4 โ 5 โ 6
์ฐ๊ฒฐ ๋ฆฌ์คํธ๋ฉด โ ๋
ธ๋์ next ํฌ์ธํฐ๋ง ๊ณจ๋ผ์ ์ฐ๊ฒฐ (๋ฐ์ดํฐ ์ด๋ ์์)
๋ฐฐ์ด์ด๋ฉด โ ์ ๋ฐฐ์ด์ ๋ณต์ฌํด์ผ ํจ (์ถ๊ฐ ๋ฉ๋ชจ๋ฆฌ O(n))
โ merge๊ฐ list์์๋ in-place๋ก ์์ฐ์ค๋ฝ๊ฒ ๋์ํฉ๋๋ค. ์ฐ๊ฒฐ ๋ฆฌ์คํธ์ ๊ตฌ์กฐ ์์ฒด๊ฐ ๋ณํฉ ์ ๋ ฌ (merge sort)์ ์ต์ ํ๋ผ ์๋ค๊ณ ๋ด๋ ๋ฉ๋๋ค.
4. ์ ๋ ฌ ์๊ณ ๋ฆฌ์ฆ ์ฐจ์ด โ introsort vs ๋ณํฉ ์ ๋ ฌ (merge sort)
std::sort โ introsort (1997, Musser)
์ธ ์๊ณ ๋ฆฌ์ฆ์ ๋จ๊ณ๋ณ๋ก ํด๋ฐฑํ๋ ํ์ด๋ธ๋ฆฌ๋. C++ ํ์ค์ด ๋ช ์์ ์ผ๋ก introsort๋ฅผ ์๊ตฌํ์ง ์์ง๋ง, ๋๋ถ๋ถ์ ํ์ค ๋ผ์ด๋ธ๋ฌ๋ฆฌ(libstdc++, libc++, MSVC)๊ฐ ์ฑํ.
1
2
3
4
5
6
7
์
๋ ฅ โ ์ฌ๊ท ๊น์ด ์ถ์
โโโ ๊น์ด < 2*logโ(n) AND ๊ตฌ๊ฐ ํฌ๊ธฐ > 16
โ โโโ quicksort (median-of-three pivot)
โโโ ๊น์ด โฅ 2*logโ(n) โ worst case ์ง์
โ โโโ heapsort ๋ก ํด๋ฐฑ (๋ณด์ฅ๋ O(n log n))
โโโ ์์ ๊ตฌ๊ฐ (โค 16)
โโโ insertion sort ๋ก ๋ง๋ฌด๋ฆฌ (์บ์ ์นํ์ )
- ์๊ฐ๋ณต์ก๋: ํ๊ท
O(n log n), ์ต์ ๋O(n log n)(heapsort ํด๋ฐฑ ๋๋ถ) - ๊ณต๊ฐ๋ณต์ก๋:
O(log n)(์ฌ๊ท ์คํ) - stable: No โ quicksort partition์ด ๋๋ฑ ์์ ์์๋ฅผ ๊นธ
- ์๊ตฌ: RandomAccessIterator
insertion sort ์์ธํ โ introsort๊ฐ ์์ ๊ตฌ๊ฐ์์ ๋ง๋ฌด๋ฆฌ๋ก ์ฐ๋ ์๊ณ ๋ฆฌ์ฆ
์นด๋ ๊ฒ์์์ ์์ ๋ ์นด๋๋ฅผ ์ ๋ ฌํ๋ ๋ฐฉ์๊ณผ ๊ฐ์ต๋๋ค. ํ ์ฅ์ฉ ๋ฝ์ ์ด๋ฏธ ์ ๋ ฌ๋ ๋ถ๋ถ์ ์๋ง์ ์๋ฆฌ์ ๋ผ์ ๋ฃ์ต๋๋ค.
๋์ ์๊ฐํ
1
2
3
4
5
6
7
8
9
10
11
์
๋ ฅ: [5, 2, 4, 6, 1, 3]
โโ | ์ผ์ชฝ์ด ์ ๋ ฌ๋ prefix, ์ค๋ฅธ์ชฝ์ด ๋ฏธ์ ๋ ฌ
step 1: [5 | 2, 4, 6, 1, 3] โ ์ฒซ ์์๋ ์์ฒด๋ก ์ ๋ ฌ
step 2: [2, 5 | 4, 6, 1, 3] โ 2๋ฅผ 5 ์์ผ๋ก ์ด๋
step 3: [2, 4, 5 | 6, 1, 3] โ 4๋ฅผ 5 ์์ผ๋ก ์ด๋
step 4: [2, 4, 5, 6 | 1, 3] โ 6์ ๊ทธ๋๋ก
step 5: [1, 2, 4, 5, 6 | 3] โ 1์ ๋งจ ์๊น์ง ์ด๋
step 6: [1, 2, 3, 4, 5, 6] โ 3์ 4 ์์ผ๋ก ์ด๋
ํต์ฌ: | ์ผ์ชฝ prefix๋ ํญ์ ์ ๋ ฌ ์ํ๋ฅผ ์ ์งํ๋ฉฐ, ์ค๋ฅธ์ชฝ ์์๋ฅผ ํ๋์ฉ ๋ผ์.
์์ฌ์ฝ๋
1
2
3
4
5
6
7
8
9
for (int i = 1; i < n; ++i) {
auto key = arr[i];
int j = i - 1;
while (j >= 0 && arr[j] > key) { // ํฐ ์์๋ค์ ํ ์นธ์ฉ ์ฐ์ธก์ผ๋ก ๋ฐ๊ธฐ
arr[j + 1] = arr[j];
--j;
}
arr[j + 1] = key; // ๋น ์๋ฆฌ์ key ์ฝ์
}
๋ณต์ก๋์ ํน์ฑ
| ํญ๋ชฉ | ๊ฐ | ๋ฉ๋ชจ |
|---|---|---|
| ํ๊ท ์๊ฐ | O(nยฒ) | ๋ผ์ ๋ฃ์ ๋๋ง๋ค ํ๊ท n/2๋ฒ ๋น๊ตยท์ด๋ |
| ์ต์ ์๊ฐ | O(nยฒ) | ์ญ์ ์ ๋ ฅ |
| ์ต์ ์๊ฐ | O(n) | ์ด๋ฏธ ์ ๋ ฌ๋ ์ ๋ ฅ โ ๋น๊ต๋ง n-1๋ฒ |
| ๊ณต๊ฐ | O(1) | in-place |
| stable | Yes | > ๋น๊ต๋ง ์ฐ๋ฉด ๋๋ฑ ์์๊ฐ ์๊ธฐ ์๋ฆฌ์ ๋ฉ์ถค |
introsort๊ฐ ์์ ๊ตฌ๊ฐ์์ insertion sort๋ฅผ ์ฐ๋ ์ด์
1
2
3
4
5
6
7
๊ตฌ๊ฐ ํฌ๊ธฐ โค 16 ์ด๋ฉด quicksort ์ฌ๊ท ๋์ insertion sort ํธ์ถ
์ด์ :
โ ์ฌ๊ท ์ค๋ฒํค๋ ์ ๊ฑฐ โ ์์ ๊ตฌ๊ฐ์ ํจ์ ํธ์ถ ๋น์ฉ์ด ๋ ํผ
โก ์บ์ ์นํ โ 16๊ฐ ์ ๋๋ฉด L1 ์บ์์ ๊ทธ๋๋ก ๋ค์ด๊ฐ
โข ๊ฑฐ์ ์ ๋ ฌ๋ ๋ฐ์ดํฐ์ ๊ฐํจ โ quicksort partition์ ๊ฑฐ์น ์์ ๊ตฌ๊ฐ์
์ด๋ฏธ ๋ถ๋ถ์ ์ผ๋ก ์ ๋ ฌ๋์ ๊ฐ๋ฅ์ฑ์ด ๋์ โ insertion sort์ best case์ ๊ทผ์
โ insertion sort๋ ์์ ๋ฐ์ดํฐ + ๊ฑฐ์ ์ ๋ ฌ๋ ๋ฐ์ดํฐ์์ quicksort๋ณด๋ค ๋น ๋ฆ ๋๋ค. ์ด ๋ ์กฐ๊ฑด์ด introsort ๋ง๋ฐ์ง์ ํญ์ ๋ง์กฑ๋๊ธฐ ๋๋ฌธ์ ๋ง๋ฌด๋ฆฌ์ฉ์ผ๋ก ์ฐ์ ๋๋ค.
std::list::sort โ ๋ณํฉ ์ ๋ ฌ (merge sort)
์ฐ๊ฒฐ ๋ฆฌ์คํธ ์ ์ฉ in-place ๋ณํฉ ์ ๋ ฌ (merge sort). ํ์ค์ ์๊ณ ๋ฆฌ์ฆ์ ๋ช ์ํ์ง ์์ง๋ง, ๋ฐ๋์ stable +
O(n log n)์ ์๊ตฌ. ์ฌ์ค์ ๋ณํฉ ์ ๋ ฌ (merge sort)๊ฐ ์ ๋ต.
1
2
3
4
5
list::sort(๋ฒ์)
โ ๋ฆฌ์คํธ๋ฅผ ์ ๋ฐ์ผ๋ก ๋ถํ (slow/fast ํฌ์ธํฐ ๋๋ ๋
ธ๋ ์นด์ดํธ)
โก ๊ฐ ์ ๋ฐ์ ์ฌ๊ท ์ ๋ ฌ
โข merge โ ๋ ์ ๋ ฌ ๋ฆฌ์คํธ์ head๋ฅผ ๋น๊ตํ๋ฉฐ ์์ ์ชฝ ๋
ธ๋๋ฅผ ๊ฒฐ๊ณผ ๋ฆฌ์คํธ ๋์ ์ฐ๊ฒฐ
(ํฌ์ธํฐ ์ฌ๋ฐฐ์น๋ง, ๋ฐ์ดํฐ ์ด๋ X)
- ์๊ฐ๋ณต์ก๋:
O(n log n)๋ณด์ฅ (worstยทaverageยทbest ๋์ผ) - ๊ณต๊ฐ๋ณต์ก๋:
O(1)โ in-place (๋ ธ๋ ์ฌ์ฐ๊ฒฐ๋ง) - stable: Yes โ merge ๋จ๊ณ์์ ๋๋ฑ ์์๋ฉด ์ผ์ชฝ(์์ชฝ)์ ๋จผ์ ์ ํ
- ์๊ตฌ: BidirectionalIterator (์ฌ์ค์ ForwardIterator๋ก๋ ์ถฉ๋ถ)
๋ณํฉ ์ ๋ ฌ (merge sort) ์์ธํ โ ๋ถํ ์ ๋ณต์ ๊ต๊ณผ์ ์ฌ๋ก
๋ณํฉ ์ ๋ ฌ์ โ๋๋ ์ ๊ฐ๊ฐ ์ ๋ ฌํ ๋ค ํฉ์น๋คโ๋ ๋ถํ ์ ๋ณต(divide and conquer) ์๊ณ ๋ฆฌ์ฆ์ ๋๋ค.
list::sort์ ๊ธฐ๋ณธ ๊ตฌํ์ด๋ฉฐ,std::stable_sort๋ ์ฌ์ค์ ๊ฐ์ ๊ณ์ด์ ๋๋ค.
3๋จ๊ณ โ ๋ถํ (Divide) / ์ ๋ณต(Conquer) / ๊ฒฐํฉ(Merge)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
์
๋ ฅ: [3, 1, 4, 1, 5, 9, 2, 6]
[1] ๋ถํ (Divide)
์ ๋ฐ์ผ๋ก ์ชผ๊ฐฌ: [3, 1, 4, 1] | [5, 9, 2, 6]
๋ ์ชผ๊ฐฌ: [3, 1] [4, 1] | [5, 9] [2, 6]
1๊ฐ๊น์ง: [3][1] [4][1] | [5][9] [2][6]
[2] ์ ๋ณต (Conquer)
1๊ฐ์ง๋ฆฌ๋ ์์ฒด๋ก ์ ๋ ฌ๋ ์ํ (base case)
[3] ๊ฒฐํฉ (Merge โ ํต์ฌ)
[1, 3] [1, 4] | [5, 9] [2, 6] โ ๋ ์ ๋ ฌ ๋ฆฌ์คํธ๋ฅผ ๋น๊ตํ๋ฉฐ ๋จธ์ง
[1, 1, 3, 4] | [2, 5, 6, 9]
[1, 1, 2, 3, 4, 5, 6, 9] โ ์ต์ข
merge ๋จ๊ณ๊ฐ ์ด๋ป๊ฒ ๋์ํ๋ (stable์ ๋น๋ฐ)
1
2
3
4
5
6
7
8
9
10
A: [1, 3] a ํฌ์ธํฐ: โ 1
B: [1, 4] b ํฌ์ธํฐ: โ 1
๊ฒฐ๊ณผ: []
step 1: *a=1, *b=1 โ ๋๋ฑ โ '<'๋ง ๋น๊ตํ๋ฏ๋ก b๊ฐ a๋ณด๋ค ์์ง ์์ โ a๋ฅผ ๋จผ์ ์ ํ
โ
stability ํต์ฌ
๊ฒฐ๊ณผ: [1(A)], aโ3
step 2: *a=3, *b=1 โ b ์์ โ b ์ ํ, ๊ฒฐ๊ณผ: [1(A), 1(B)], bโ4
step 3: *a=3, *b=4 โ a ์์ โ a ์ ํ, ๊ฒฐ๊ณผ: [1(A), 1(B), 3], a ๋
step 4: B์ ๋จ์ ๋ถ๋ถ [4] ์ด์ด๋ถ์ โ [1(A), 1(B), 3, 4]
โ ์ฝ๋ ํ ์ค(if (*b < *a)๋ก b๋ฅผ ๋จผ์ ์ ํ)์์ <๋ง ์ฐ๊ณ <=๋ฅผ ์ฐ์ง ์์ผ๋ฉด ๋๋ฑ ์์์ผ ๋ a(์ผ์ชฝ ์ํ์ค)๊ฐ ํญ์ ๋จผ์ ๋์ค๊ฒ ๋์ด ์์ ์ฑ์ด ์์ฐ์ค๋ฝ๊ฒ ๋ณด์กด๋ฉ๋๋ค.
์๊ฐ๋ณต์ก๋ ๋ถ์ (๋ง์คํฐ ์ ๋ฆฌ)
1
2
3
4
5
6
7
8
T(n) = 2 * T(n/2) + O(n)
โโ ๋ ์ ๋ฐ โโ โ merge ํ ๋ฒ โ
๊น์ด = logโ n (์ ๋ฐ์ฉ ์ชผ๊ฐ๋๊น)
๊ฐ ๊น์ด์ ์์
๋ = O(n) (๊ทธ ๊น์ด์ ๋ชจ๋ ๋จธ์ง๋ฅผ ํฉ์น๋ฉด n๊ฐ ๋น๊ต)
โ ์ด ๋น์ฉ = O(n log n)
worst = average = best = O(n log n) โ quicksort์ ๋ฌ๋ฆฌ ์
๋ ฅ ๋ชจ์์ ๋ฌด๊ด
๋ ๊ฐ์ง ๊ตฌํ ๋ฐฉ์ โ top-down vs bottom-up
| ๋ฐฉ์ | ๋์ | ํน์ง |
|---|---|---|
| Top-down (์ฌ๊ท) | ํฐ ๋ฒ์๋ฅผ ์ ๋ฐ์ผ๋ก ์ชผ๊ฐ๋ฉฐ ์ฌ๊ท ํธ์ถ | ์ง๊ด์ . O(log n) ์คํ ์ฌ์ฉ |
| Bottom-up (๋ฐ๋ณต) | 1๊ฐ์ฉ ์ง์ง์ด ๋จธ์ง โ 2๊ฐ์ฉ โ 4๊ฐ์ฉ โฆ | ์คํ ์์ด ๋ฐ๋ณต๋ฌธ. ์บ์ ์นํ์ |
โ std::list::sort๋ ๋ณดํต bottom-up ๋ฐฉ์์ผ๋ก ๊ตฌํ๋ฉ๋๋ค (libstdc++ ๋ฑ). ์ฌ๊ท ์คํ์ ์ ์จ์ O(1) ์ถ๊ฐ ๋ฉ๋ชจ๋ฆฌ๋ฅผ ๋ณด์ฅํ๊ธฐ ์ข๊ณ , ๋จธ์ง ๋จ์๋ฅผ 1, 2, 4, 8, 16 โฆ ์ผ๋ก ํค์๊ฐ๋ฉฐ ์งํํฉ๋๋ค.
์ list์ ์์ฐ์ค๋ฌ์ด๊ฐ โ ๊ฒฐ์ ํ
1
2
3
4
5
๋ฐฐ์ด ๋จธ์ง: ๋ ์ ๋ ฌ๋ ๋ถ๋ถ์ ๋จธ์งํ๋ ค๋ฉด ๊ฒฐ๊ณผ ๋ด์ ์ ๋ฐฐ์ด ํ์ (O(n) ์ถ๊ฐ ๋ฉ๋ชจ๋ฆฌ)
in-place๋ก๋ ๊ฐ๋ฅํ์ง๋ง ์๊ณ ๋ฆฌ์ฆ์ด ๋งค์ฐ ๋ณต์ก (Knuth, Pratt ๋ฑ)
list ๋จธ์ง: ๋ ์ ๋ ฌ๋ ๋ฆฌ์คํธ์ ๋
ธ๋ next ํฌ์ธํฐ๋ง ๋ค์ ์๊ธฐ
โ ์ถ๊ฐ ๋ฉ๋ชจ๋ฆฌ O(1), ๋ฐ์ดํฐ ์ด๋ 0, ์์ ์ฑ ์์ฐ์ค๋ฌ์
โ ์ฐ๊ฒฐ ๋ฆฌ์คํธ์ ์๋ฃ๊ตฌ์กฐ ์์ฒด๊ฐ ๋ณํฉ ์ ๋ ฌ์ ๋จธ์ง ๋จ๊ณ์ ์๋ฒฝํ ๋ง๋ฌผ๋ฆฝ๋๋ค. ์ด๊ฒ std::list๊ฐ sort ๋ฉค๋ฒ ํจ์๋ก ๋ณํฉ ์ ๋ ฌ (merge sort)์ ์ฑํํ ๊ฐ์ฅ ๊ฐ๋ ฅํ ์ด์ ์ ๋๋ค.
๋จ์ โ ์บ์ ์นํ์ฑ
1
2
3
4
5
6
๋ฐฐ์ด + ๋ณํฉ ์ ๋ ฌ: ๋ฐ์ดํฐ๊ฐ ์ฐ์๋ ๋ฉ๋ชจ๋ฆฌ โ ์บ์ ํํธ์จ ๋์
list + ๋ณํฉ ์ ๋ ฌ: ๋
ธ๋๊ฐ ํ ๊ณณ๊ณณ์ ๋ถ์ฐ โ ์บ์ ๋ฏธ์ค ๋น๋ฐ
๊ทธ๋์ vector + std::sort(introsort)๊ฐ list + list::sort๋ณด๋ค ๋ณดํต 5~10๋ฐฐ ๋น ๋ฆ.
list::sort๋ ์ด๋๊น์ง๋ "list๋ฅผ ์จ์ผ๋ง ํ๋ ์ํฉ์์์ ์ต์ "์ด์ง,
list๊ฐ vector๋ณด๋ค ์ ๋ ฌ์์ ๋น ๋ฅด๋ค๋ ์๋ฏธ๊ฐ ์ ๋ ์๋.
โ 13๋ฒ์์ ๋ณธ โlist๊ฐ ์ ๋นํ๋๋ ์๋๋ฆฌ์คโ(ํฐ ๊ฐ์ฒด + ์ฆ์ splice + iterator ์์ ์ฑ)์ ๋ค์ด๋ง์ ๋๋ง list::sort์ ์ด์ ์ด ๋ฐํ๋ฉ๋๋ค.
๋น๊ต ํ
| ํญ๋ชฉ | std::sort (introsort) | std::list::sort (๋ณํฉ ์ ๋ ฌ / merge sort) |
|---|---|---|
| ์๊ณ ๋ฆฌ์ฆ | quicksort + heapsort + insertion sort | ๋ณํฉ ์ ๋ ฌ (merge sort) |
| ์๊ฐ๋ณต์ก๋ (ํ๊ท ) | O(n log n) | O(n log n) |
| ์๊ฐ๋ณต์ก๋ (์ต์ ) | O(n log n) (heapsort ํด๋ฐฑ) | O(n log n) |
| ๊ณต๊ฐ๋ณต์ก๋ | O(log n) ์ฌ๊ท | O(1) in-place |
| ์์ ์ฑ | Unstable | Stable |
| ๋ฐ์ดํฐ ์ด๋ | swap ๋ค์ (๊ฐ์ฒด ๋ณต์ฌยท์ด๋) | 0 (๋ ธ๋ ํฌ์ธํฐ ์ฌ์ฐ๊ฒฐ) |
| ์บ์ ์นํ์ฑ | ๋งค์ฐ ๋์ (์ฐ์ ๋ฉ๋ชจ๋ฆฌ) | ๋ฎ์ (๋ ธ๋ ๋ถ์ฐ) |
| ๋น๊ต ํจ์ | strict weak ordering | strict weak ordering |
| iterator ์๊ตฌ | RandomAccess | Bidirectional |
โ ์ด๋ก ๋ณต์ก๋๋ ๊ฐ์ง๋ง, ๋ฐ์ดํฐ ์ด๋ ๋น์ฉ๊ณผ ์บ์ ์นํ์ฑ์์ ๋์ ์ ๋ฐ๋ ํน์ฑ์ ๋ณด์ ๋๋ค.
5. ๋ ธ๋ ์ฌ์ฐ๊ฒฐ โ ๋ฐ์ดํฐ ์ด๋ ๋น์ฉ 0์ ์๋ฏธ
ํต์ฌ ํ ๋ฌธ์ฅ
std::list::sort๋ ๋ ธ๋ ์์ฒด๋ฅผ ์ฎ๊ธฐ์ง ์๊ณ prev/next ํฌ์ธํฐ๋ง ์ฌ์ฐ๊ฒฐํด์ ์ ๋ ฌํฉ๋๋ค. ํฐ ๊ฐ์ฒด๋ฅผ ๋ด๊ณ ์์์๋ก ์ด ์ฐจ์ด๊ฐ ์ค์ธก ์ฑ๋ฅ์ ๊ฐ๋ฆ ๋๋ค.
์๊ฐํ โ merge ํ ๋จ๊ณ
1
2
3
4
5
6
7
8
9
10
11
12
13
์ด๊ธฐ (๋ ์ ๋ ฌ ๋ฆฌ์คํธ)
A: [1] โโ [3] โโ [5]
B: [2] โโ [4] โโ [6]
merge ์งํ (ํฌ์ธํฐ๋ง ์ฌ๋ฐฐ์น)
โโโโโโโโโโโโโโโโโโ
[1] โโnextโโโ โผ
โโโโโโโโโโโโโโโโโ[2]โโnextโโ ...
[3] โโnextโโโ
(๊ฐ์ฒด 1, 3, 5, 2, 4, 6 ์ ๋ฉ๋ชจ๋ฆฌ ์ฃผ์๋ ๊ทธ๋๋ก!)
๊ฒฐ๊ณผ (๋จ์ผ ์ ๋ ฌ ๋ฆฌ์คํธ)
[1] โโ [2] โโ [3] โโ [4] โโ [5] โโ [6]
โ ๋ ธ๋ ์์ฒด๋ ์ฒ์ ํ ๋น๋ ์๋ฆฌ์ ๊ทธ๋๋ก, ๋จ์ง next/prev๊ฐ ๋ค๋ฅธ ๋ ธ๋๋ฅผ ๊ฐ๋ฆฌํค๊ฒ ๋ฐ๋ ๊ฒ๋ฟ์ ๋๋ค. ๊ฐ์ฒด ๋ณต์ฌ ์์ฑ์๋ ์ด๋ ์์ฑ์๋ ํ ๋ฒ๋ ํธ์ถ๋์ง ์์ต๋๋ค.
vector + std::sort ์์ ๋น๊ต
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
struct LargeObject {
char data[1024];
bool operator<(const LargeObject& o) const { /* ... */ }
};
// vector ์ผ์ด์ค
std::vector<LargeObject> v(10000);
std::sort(v.begin(), v.end());
// โ partitionยทmerge ๋จ๊ณ๋ง๋ค 1024๋ฐ์ดํธ ๊ฐ์ฒด๋ฅผ swap (memcpy ๋ค์)
// โ ์ค์ธก: ๋ฐ์ดํฐ ์ด๋ ๋น์ฉ์ด ๋น๊ต ๋น์ฉ๋ณด๋ค ํจ์ฌ ํผ
// list ์ผ์ด์ค
std::list<LargeObject> lst(10000);
lst.sort();
// โ ๋
ธ๋ ํฌ์ธํฐ(8๋ฐ์ดํธ ร 2)๋ง ์ฌ๋ฐฐ์น
// โ ๊ฐ์ฒด ์์ฒด์ 1024๋ฐ์ดํธ๋ ํ ๋ฒ๋ ์ ์ฎ๊น
โ ์ด๊ฒ list๊ฐ ์ ๋นํ๋๋ ๊ฑฐ์ ์ ์ผํ ์ค์ฉ์ ์๋๋ฆฌ์ค์ ๋๋ค (13๋ฒ 6์ฅ ์ฐธ๊ณ ). โํฐ ๊ฐ์ฒด + ์ฆ์ ์ ๋ ฌยทsplice + iterator ์์ ์ฑโ์ด ๋์์ ๋ง์กฑ๋ผ์ผ ํ์ง๋ง, ๋งค์ฐ ๋๋ฌผ๊ธด ํฉ๋๋ค.
iterator ์์ ์ฑ (๋ค)
list::sort๋ iterator๋ฅผ ๋ฌดํจํํ์ง ์์ต๋๋ค. ์ฌ๋ฐฐ์น ํ์๋ ๋ ธ๋ ์์ฒด๊ฐ ๊ทธ๋๋ก ์ด์์์ผ๋ ๋ ธ๋๋ฅผ ๊ฐ๋ฆฌํค๋ iterator๋ ์ฌ์ ํ ๊ฐ์ ๊ฐ์ ๊ฐ๋ฆฌํต๋๋ค (์์น๋ ๋ฐ๋์์ง๋ง).
1
2
3
4
5
std::list<int> lst = {3, 1, 4, 1, 5};
auto it = std::next(lst.begin()); // ๋ ๋ฒ์งธ ์์ = 1
lst.sort();
// lst = {1, 1, 3, 4, 5}
*it; // ์ฌ์ ํ 1 (๋
ธ๋๋ ์ด์์์)
โ vector์๋ค๋ฉด std::sort ํ iterator๊ฐ ๊ฐ๋ฆฌํค๋ ๊ฐ์ด ์์ ํ ๋ฌ๋ผ์ง๊ฑฐ๋ ๋ฌดํจํ๋ ์ ์์ต๋๋ค.
6. stable ์ฌ๋ถ / ์ถ๊ฐ ๋ฉ๋ชจ๋ฆฌ ๋น๊ต
stable์ด ๋ญ์ง ํ์ด์ โ โ๋๋ฑ ์์์ ์๋ ์์ ์ ์งโ์ ์ง์ง ์๋ฏธ
ํ ์ค๋ก: ์ ๋ ฌ ํค๋ ๊ฐ์๋ฐ ๋ค๋ฅธ ์ ๋ณด๋ ๋ค๋ฅธ ๋ ์์๊ฐ, ์ ๋ ฅ์์ ์ด๋ ์ชฝ์ด ์์ด์๋์ง๋ฅผ ์ ๋ ฌ ํ์๋ ๊ทธ๋๋ก ๋ณด์กดํ๋ ๊ฒ.
โ๋๋ฑโ์ด ํท๊ฐ๋ฆฌ๋ ์ด์
โ๋๋ฑ ์์โ๋ผ๋ ๋ง์ด โ์์ ํ ๋๊ฐ์ ์์โ์ฒ๋ผ ๋ค๋ฆฌ์ง๋ง, ์ ํํ๋ ์ ๋ ฌ ๋น๊ต ํจ์๊ฐ ๋ ์ฌ์ด์ ์ฐ์ด์ ๊ฐ๋ฆฌ์ง ๋ชปํ๋ ์์์ ๋๋ค. ์ ๋ ฌ ํค๋ง ๊ฐ๊ณ ๋ค๋ฅธ ๋ฐ์ดํฐ(์ด๋ฆยท๋ ์ง ๋ฑ)๋ ์ผ๋ง๋ ์ง ๋ค๋ฅผ ์ ์์ต๋๋ค.
1
2
3
struct Employee { std::string name; int dept; };
// ๋ถ์(dept)๋ก๋ง ์ ๋ ฌํ๋ฉด โ ๋ถ์๊ฐ ๊ฐ์ ๋ ์ฌ์์ cmp ์
์ฅ์์ "๋๋ฑ"
// (์ด๋ฆ์ด ๋ฌ๋ผ๋ cmp๋ ์ ๊ฒฝ X)
์ฌ๋ก๋ก ๋ณด๋ stable vs unstable
1
2
3
4
5
6
7
8
9
10
11
์
๋ ฅ: [Alice/ํ1, Bob/ํ2, Charlie/ํ1, Dave/ํ2, Eve/ํ1]
(ํ ๋ฒํธ๋ก๋ง ์ ๋ ฌ)
stable ๊ฒฐ๊ณผ (๋ณด์ฅ):
[Alice/ํ1, Charlie/ํ1, Eve/ํ1, Bob/ํ2, Dave/ํ2]
โ ํ1 ์: Alice โ Charlie โ Eve (์
๋ ฅ ์์ ๊ทธ๋๋ก)
โ ํ2 ์: Bob โ Dave (์
๋ ฅ ์์ ๊ทธ๋๋ก)
unstable ๊ฒฐ๊ณผ (์์ 1๊ฐ์ง):
[Eve/ํ1, Alice/ํ1, Charlie/ํ1, Dave/ํ2, Bob/ํ2]
โ ํ1 ์ ์์๊ฐ ๋ค์์ (๋ณด์ฅ์ด ์์ ๋ฟ, ์ฐ์ฐํ ์ ์ง๋ ์๋ ์์)
โ unstable์ด๋ผ๊ณ ํด์ ํญ์ ์์๊ฐ ๊นจ์ง๋ ๊ฒ ์๋๋ผ, ๋ณด์ฅํ์ง ์๋๋ค๋ ๋ป์ ๋๋ค. ๊ฐ์ ์ ๋ ฅ + ๊ฐ์ ์๊ณ ๋ฆฌ์ฆ์ด๋ฉด ๊ฒฐ๊ณผ๊ฐ ๊ฐ์ ์ ์์ง๋ง ์ผ๋ฐ์ ์ผ๋ก๋ ์์กดํ๋ฉด ์ ๋ฉ๋๋ค.
์ ์ค๋ฌด์์ ์ค์ํ๊ฐ โ ๋ค๋จ๊ณ ์ ๋ ฌ
1
2
3
4
5
6
7
8
์๊ตฌ: "์ฌ์์ ๋ถ์๋ณ๋ก, ๊ฐ์ ๋ถ์ ์์์ ์
์ฌ์ผ ์์๋ก ์ ๋ ฌ"
ํด๊ฒฐ์ฑ
(stable_sort ํ์ฉ):
โ ๋จผ์ ์
์ฌ์ผ๋ก ์ ๋ ฌ (sort ๋๋ stable_sort ์๋ฌด๊ฑฐ๋)
โก ๊ทธ ๋ค์ ๋ถ์๋ก stable_sort
โ โก๊ฐ stable์ด๋ฉด โ ์์ ๋ง๋ ์
์ฌ์ผ ์์๊ฐ ๊ฐ์ ๋ถ์ ์์์ ์ ์ง๋จ
๋ง์ฝ โก๋ฅผ unstable sort๋ก ํ๋ฉด โ ์ ์ ๋ ฌ์ด ๋ฌด์๋ฏธํด์ง.
โ ๋ค๋จ๊ณ ์ ๋ ฌยท์ธ๋ถ์์ ๋ฏธ๋ฆฌ ๋ง๋ ์์ ๋ณด์กด ๊ฐ์ ์๋๋ฆฌ์ค์์ stable ์ฌ๋ถ๊ฐ ์ ๋ต์ ๊ฐ๋ฆ ๋๋ค.
stable์ ํ์ ์ ์
๋๋ฑํ ์์(
!(a < b) && !(b < a)์ธ ์์)๋ค์ ์๋์ ์์๋ฅผ ์ ๋ ฅ ๊ทธ๋๋ก ์ ์งํ๋ ์ ๋ ฌ.
1
2
3
4
5
6
7
8
9
10
11
std::vector<std::pair<int, char>> v = {
{1, 'a'}, {2, 'b'}, {1, 'c'}, {2, 'd'}, {1, 'e'}
};
auto cmp = [](const auto& x, const auto& y){ return x.first < y.first; };
std::sort(v.begin(), v.end(), cmp);
// ๊ฐ๋ฅ ๊ฒฐ๊ณผ 1: (1,a) (1,c) (1,e) (2,b) (2,d) โ ์ด ์ข๊ฒ ์ ์ง
// ๊ฐ๋ฅ ๊ฒฐ๊ณผ 2: (1,e) (1,a) (1,c) (2,d) (2,b) โ ์์ ๊นจ์ง โ ๋ณด์ฅ X
std::stable_sort(v.begin(), v.end(), cmp);
// ํญ์: (1,a) (1,c) (1,e) (2,b) (2,d) โ ๋ณด์ฅ
list::sort๋ ์ stable ๋ณด์ฅ์ธ๊ฐ
๋ณํฉ ์ ๋ ฌ (merge sort)์ merge ๋จ๊ณ์์ ๋ ๋ถ๋ถ์ด ๋๋ฑํ ๋ ์ผ์ชฝ(์)์ ๋จผ์ ์ ํํ๋๋ก ๊ตฌํํ๋ฉด ์์ฐ์ค๋ฝ๊ฒ stable์ด ๋ฉ๋๋ค.
1
2
3
4
5
// merge ์์ฌ์ฝ๋
while (a != A.end() && b != B.end()) {
if (*b < *a) take_from(b); // โ b๊ฐ *์๊ฒฉํ* ์์ ๋๋ง b๋ฅผ ๋จผ์
else take_from(a); // ๋๋ฑํ๋ฉด a (์ผ์ชฝ)๋ฅผ ๋จผ์ โ stability ์ ์ง
}
ํ์ค์ std::list::sort์ stable ๋ณด์ฅ์ ๋ช
์ํฉ๋๋ค. std::sort๋ stable์ ๋ณด์ฅํ์ง ์์ผ๋ฏ๋ก stable์ด ํ์ํ๋ฉด std::stable_sort๋ฅผ ์จ์ผ ํฉ๋๋ค.
์ถ๊ฐ ๋ฉ๋ชจ๋ฆฌ ๋น๊ต
| ํจ์ | ์ถ๊ฐ ๋ฉ๋ชจ๋ฆฌ | ๋น๊ณ |
|---|---|---|
std::sort | O(log n) | ์ฌ๊ท ์คํ |
std::list::sort | O(1) | in-place ๋ ธ๋ ์ฌ์ฐ๊ฒฐ |
std::stable_sort | O(n) ๋๋ O(n logยฒ n) | ์ถ๊ฐ ๋ฒํผ ํ๋ณด ๊ฐ๋ฅ ์ O(n), ์คํจ ์ O(n logยฒ n) ์๊ฐ |
โ std::stable_sort๋ ๋ฉ๋ชจ๋ฆฌ๋ฅผ ๋ชป ์ก์ผ๋ฉด ์๊ฐ๋ณต์ก๋๊ฐ O(n logยฒ n)๋ก ๋จ์ด์ง๋๋ค (in-place ๋ณํฉ ์ ๋ ฌ (merge sort)). ๋ฐ๋ฉด list::sort๋ ๋
ธ๋ ์ฌ์ฐ๊ฒฐ์ด ์์ฐ์ค๋ฝ๊ฒ in-place๋ผ ํญ์ O(n log n) + O(1).
๋น๊ต ์ ๋ฆฌ
| ํญ๋ชฉ | std::sort | std::list::sort | std::stable_sort |
|---|---|---|---|
| stable | No | Yes | Yes |
| ์ถ๊ฐ ๋ฉ๋ชจ๋ฆฌ | O(log n) | O(1) | O(n) ๋๋ O(n logยฒ n) ์๊ฐ |
| ์๊ฐ (๋ณด์ฅ) | O(n log n) | O(n log n) | O(n log n) ๋๋ O(n logยฒ n) |
7. forward_list::sort โ ๊ฐ์ ์ด์ ๋ก ๋ ๋ฐ๋ก
ํต์ฌ ํ ๋ฌธ์ฅ
std::forward_list(๋จ๋ฐฉํฅ ์ฐ๊ฒฐ ๋ฆฌ์คํธ)๋ ForwardIterator๋ง ์ง์ํด์std::sort๋ ๋ฌผ๋กBidirectionalIterator๊ฐ ํ์ํ ์ผ๋ถ ์๊ณ ๋ฆฌ์ฆ๋ ๋ชป ์๋๋ค. ๊ทธ๋์forward_list::sort๋ ๋ฉค๋ฒ ํจ์๋ก ๋ฐ๋ก ์์ต๋๋ค.
์๊ทธ๋์ฒ
1
2
3
4
5
template <class Compare>
void forward_list<T>::sort(Compare comp);
template <>
void forward_list<T>::sort(); // ๊ธฐ๋ณธ < ๋น๊ต
์นดํ ๊ณ ๋ฆฌ ๋น๊ต
| ์ปจํ ์ด๋ | iterator | ๋ฉค๋ฒ sort | ์๊ณ ๋ฆฌ์ฆ sort |
|---|---|---|---|
vector, deque, array | RandomAccess | ์์ (๋ถํ์) | std::sort OK |
list | Bidirectional | list::sort | ์ปดํ์ผ ์๋ฌ |
forward_list | Forward | forward_list::sort | ์ปดํ์ผ ์๋ฌ |
forward_list๋ง์ ์ถ๊ฐ ์ ์ฝ
--it์ ๋จ โ ๋์์๋ถํฐ ์ญ๋ฐฉํฅ ์ํ ๋ถ๊ฐsize()๋ฉค๋ฒ ํจ์๋ ์์ (O(1) ๋ณด์ฅ ๋ถ๊ฐ๋ผ ์๋์ ์ผ๋ก ์ ๊ฑฐ)- ๊ทธ๋์ ์ ๋ ฌ ๊ตฌํ์ ๋ ธ๋ ์นด์ดํธ๋ฅผ ์ง์ ์ธ๊ฑฐ๋ bottom-up ๋ณํฉ ์ ๋ ฌ (merge sort) ์ฌ์ฉ
โ ๋จ๋ฐฉํฅ์ด๋ผ ๋๋์ฑ ์ธ๋ถ ์๊ณ ๋ฆฌ์ฆ์ด ์๋ ์๊ฐ ์๋ ์๋ฃ๊ตฌ์กฐ์ด๊ณ , ๋ฉค๋ฒ ํจ์๊ฐ ๋ฐ๋ก ์์ด์ผ ํ๋ ๋น์์ฑ์ด ๋ ๊ฐํฉ๋๋ค.
๊ฐ์ ํจํด์ ๋ฉค๋ฒ ํจ์๋ค
1
2
3
4
5
list::sort() / forward_list::sort() โ ์ ๋ ฌ
list::merge(other) / forward_list::merge(other) โ ์ ๋ ฌ๋ ๋ฆฌ์คํธ ๋ณํฉ (๋
ธ๋ ์ด์ )
list::splice(...) / forward_list::splice_after(...) โ ๋
ธ๋ ์ด์
list::unique() / forward_list::unique() โ ์ธ์ ์ค๋ณต ์ ๊ฑฐ
list::reverse() / forward_list::reverse() โ ์ญ์ํ
โ ๋ชจ๋ ๋ ธ๋ ํฌ์ธํฐ ์ฌ์ฐ๊ฒฐ๋ก O(?) ๋น์ฉ์ ์ค์ผ ์ ์๋ ์ฐ์ฐ๋ค. ์๊ณ ๋ฆฌ์ฆ์ผ๋ก ๊ตฌํํ๋ฉด ๋ฐ์ดํฐ ์ด๋์ด ๋ฐ์ํ์ง๋ง, ๋ฉค๋ฒ ํจ์๋ ํฌ์ธํฐ๋ง ๋ง์ง๋๋ค.
8. ๋ฉค๋ฒ vs ์๊ณ ๋ฆฌ์ฆ ์ปจ๋ฒค์ โ set/map::find์ ๊ฐ์ ํจํด
ํต์ฌ ํ ๋ฌธ์ฅ
โ์๋ฃ๊ตฌ์กฐ์ ํน์ฑ์ ์๊ณ ๋ฆฌ์ฆ์ด ํ์ฉํ ์ ์์ ๋, ๋ฉค๋ฒ ํจ์๊ฐ ๋ฐ๋ก ์กด์ฌํ๋คโ โ ์ด๊ฒ STL ์ ์ฒด์ ์ผ๊ด๋๊ฒ ํ๋ฅด๋ ์ค๊ณ ์์น์ ๋๋ค.
๊ฐ์ ์ปจ๋ฒค์ ์ ์ฌ๋ก ๋ชจ์
| ์๋ฃ๊ตฌ์กฐ | ๋ฉค๋ฒ ํจ์ | ์๊ณ ๋ฆฌ์ฆ ํจ์ | ์ด์ |
|---|---|---|---|
std::set / std::map | find() O(log n) | std::find O(n) | RB-Tree ๊ตฌ์กฐ ํ์ฉ |
std::unordered_map | find() O(1) ํ๊ท | std::find O(n) | ํด์ ๋ฒํท ์ ํ |
std::list | sort() O(n log n) stable | std::sort ์ปดํ์ผ ์๋ฌ | ๋ ธ๋ ์ฌ์ฐ๊ฒฐ + iterator ์นดํ ๊ณ ๋ฆฌ |
std::forward_list | sort() O(n log n) stable | std::sort ์ปดํ์ผ ์๋ฌ | ๋จ๋ฐฉํฅ + ๋ ธ๋ ์ฌ์ฐ๊ฒฐ |
std::list | merge(), splice(), unique(), reverse() | ์๊ณ ๋ฆฌ์ฆ์ ๋ฐ์ดํฐ ์ด๋ | ๋ ธ๋ ์ฌ์ฐ๊ฒฐ |
std::set / std::map | lower_bound(), upper_bound(), equal_range() | ์๊ณ ๋ฆฌ์ฆ ๋ฒ์ ์กด์ฌํ๋ ๋ฉค๋ฒ๊ฐ ๋ ๋น ๋ฆ | ํธ๋ฆฌ ๊ตฌ์กฐ ํ์ฉ |
std::set / std::map | count() O(log n) | std::count O(n) | ํธ๋ฆฌ ๊ตฌ์กฐ ํ์ฉ |
ํ ์ค๋ก
1
2
๋ฉค๋ฒ ํจ์๊ฐ ์๋ค๋ฉด ๊ฑฐ์ ํญ์ ๊ทธ๊ฒ ๋ ๋น ๋ฅด๊ฑฐ๋, ๋ ์์ ํ๊ฑฐ๋, ์๊ณ ๋ฆฌ์ฆ์ด ์์ ๋ชป ์ฐ๋ ์ผ์ด์ค๋ค.
โ STL ๋ฉค๋ฒ vs ์๊ณ ๋ฆฌ์ฆ ์ปจ๋ฒค์
๊ฒฐ์ ํ๋ฆ
1
2
3
4
5
6
7
8
9
์ด ์ปจํ
์ด๋์ sort/find/count/equal_range ๋ฑ ๋ฉค๋ฒ ํจ์๊ฐ ์๋?
โ
โโโโโโดโโโโโ
์ ์๋์ค
โ โ
๋ฉค๋ฒ ํจ์ ์๊ณ ๋ฆฌ์ฆ ํจ์ ์ฌ์ฉ
์ฌ์ฉ (โ
) (vectorยทdequeยทarray ๊ฐ์ RandomAccess)
โ
"์๋ฃ๊ตฌ์กฐ ํน์ฑ์ ์ด๋ ค ๋ ๋น ๋ฅด๊ฑฐ๋, ์๊ณ ๋ฆฌ์ฆ์ ์ปดํ์ผ๋ ์ ๋จ"
9. ๊ด๋ จ ์ ๋ ฌ family โ stable_sort / partial_sort / nth_element
๋น๊ต ํ
| ํจ์ | ์๊ฐ๋ณต์ก๋ | ์ถ๊ฐ ๋ฉ๋ชจ๋ฆฌ | stable | ์ฉ๋ |
|---|---|---|---|---|
std::sort | O(n log n) | O(log n) | No | ์ผ๋ฐ ์ ๋ ฌ |
std::stable_sort | O(n log n) ๋๋ O(n logยฒ n) | O(n) ์๋ | Yes | ์์ ์ ๋ ฌ ํ์ |
std::partial_sort | O(n log k) | O(1) | No | ์์ k๊ฐ๋ง ์ ๋ ฌ |
std::nth_element | O(n) ํ๊ท | O(1) | No | k๋ฒ์งธ ์์๋ง ์ ์๋ฆฌ์ |
std::sort_heap | O(n log n) | O(1) | No | heap โ ์ ๋ ฌ ๋ณํ |
std::list::sort | O(n log n) | O(1) | Yes | list ์ ์ฉ in-place merge |
std::forward_list::sort | O(n log n) | O(1) | Yes | forward_list ์ ์ฉ |
ํต์ฌ ์ฝ๋ ์์
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
std::vector<int> v = {3, 1, 4, 1, 5, 9, 2, 6};
// (1) ์ผ๋ฐ ์ ๋ ฌ โ ๊ฐ์ฅ ์์ฃผ ์
std::sort(v.begin(), v.end());
// {1, 1, 2, 3, 4, 5, 6, 9}
// (2) ์์ ์ ๋ ฌ โ ๋๋ฑ ์์ ์์ ์ ์ง ํ์
std::stable_sort(v.begin(), v.end());
// (3) ์์ 3๊ฐ๋ง ์ ๋ ฌ (์ ์ฒด ์ ๋ ฌ์ ์ ํจ)
std::partial_sort(v.begin(), v.begin() + 3, v.end());
// {1, 1, 2, ...๋ค๋ ์ ๋ ฌ ์ ๋จ...}
// (4) k๋ฒ์งธ ์์(์ค์๊ฐ ๋ฑ) ๋ง ์ ์๋ฆฌ์
std::nth_element(v.begin(), v.begin() + v.size()/2, v.end());
// ์ค์๊ฐ์ด v[n/2]์ ์์น, ์ข์ธก์ ๋ ์๊ฑฐ๋ ๊ฐ์, ์ฐ์ธก์ ๋ ํฌ๊ฑฐ๋ ๊ฐ์ โ ํ๊ท O(n)
โ ์์ k๊ฐ๋ง ํ์ํ๋ฉด partial_sort, k๋ฒ์งธ ์์๋ง ํ์ํ๋ฉด nth_element. ์ ์ฒด ์ ๋ ฌ๋ณด๋ค ๋น ๋ฆ
๋๋ค.
์์ ์ฑ์ด ์ค์ํ ์ผ์ด์ค
1
2
3
4
5
6
7
struct Employee { std::string name; int dept; };
std::vector<Employee> emps = { ... };
// ๋ถ์๋ณ๋ก ์ ๋ ฌํ๋ ๊ฐ์ ๋ถ์ ์์์ ์
๋ ฅ ์์ ์ ์งํ๊ณ ์ถ๋ค
std::stable_sort(emps.begin(), emps.end(),
[](const auto& a, const auto& b){ return a.dept < b.dept; });
// ๊ฐ์ dept ์์์ ์๋ ์
๋ ฅ ์์๋๋ก (์ด๋ฆ์ ๋ฑ)
โ std::sort์๋ค๋ฉด ๊ฐ์ ๋ถ์ ์์์ ์์์ ์์๊ฐ ๋์ด๋ฒ๋ฆฝ๋๋ค.
10. ์ธ๋ฆฌ์ผ์์์ ์ ๋ ฌ โ Algo::Sort / TArray::Sort / TLinkedList
๋์ ํ
| std:: | Unreal Algo:: / ๋ฉค๋ฒ | ๋น๊ณ |
|---|---|---|
std::sort | Algo::Sort(Range) | introsort ๊ธฐ๋ฐ |
std::sort | TArray::Sort() (๋ฉค๋ฒ) | ์์ ์ฑ ๋ณด์ฅ X |
std::stable_sort | Algo::StableSort(Range) | ์์ ์ ๋ ฌ |
std::stable_sort | TArray::StableSort() (๋ฉค๋ฒ) | ์์ ์ ๋ ฌ |
std::partial_sort | (์ง์ ๋์ ์์) | Algo::HeapSort + ์๋ฅด๊ธฐ ๋ฑ ์กฐํฉ |
std::nth_element | (์ง์ ๋์ ์์) | ์๋ ๊ตฌํ |
std::list::sort | (๋์ ์์) | TLinkedList์ sort ๋ฉค๋ฒ ํจ์ X โ ์๋ ๊ตฌํ |
์ฝ๋ ์์
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
#include "Algo/Sort.h"
#include "Algo/StableSort.h"
TArray<int32> Arr = {3, 1, 4, 1, 5, 9, 2, 6};
// (1) ๋ฉค๋ฒ ํจ์ โ ๊ฐ์ฅ ์ผ๋ฐ์
Arr.Sort(); // ๊ธฐ๋ณธ < ์ค๋ฆ์ฐจ์
Arr.Sort([](int32 A, int32 B){ return A > B; }); // ๋ด๋ฆผ์ฐจ์ ๋๋ค
// (2) Algo::Sort โ std::sort ๋์
Algo::Sort(Arr);
Algo::Sort(Arr, [](int32 A, int32 B){ return A < B; });
// (3) ์์ ์ ๋ ฌ
Arr.StableSort();
Algo::StableSort(Arr);
TLinkedList โ std::list ๋์์ด 1๊ธ์ด ์๋ ์ด์
1
2
3
4
// ์ธ๋ฆฌ์ผ์ TLinkedList๋ ์๋์ ์ผ๋ก ๊ฐ๋ฒผ์ด ํฌํผ ์์ค
TLinkedList<int32> List;
// โ Sort() ๋ฉค๋ฒ ํจ์ ์์
// โ ์ ๋ ฌ์ด ํ์ํ๋ค๋ฉด TArray<int32>๋ก ์ฎ๊ธฐ๊ฑฐ๋ ์๋ ๋ณํฉ ์ ๋ ฌ (merge sort)
โ ์ธ๋ฆฌ์ผ์ด cache ์นํ์ ์๋ฃ๊ตฌ์กฐ(TArray)๋ฅผ 1๊ธ์ผ๋ก ๋๊ณ ์ฐ๊ฒฐ ๋ฆฌ์คํธ๋ฅผ ๋ถ์์ ์ผ๋ก ๋ค๋ฃจ๋ ์ฒ ํ(13๋ฒ 7์ฅ ์ฐธ๊ณ )์ด ์ ๋ ฌ์์๋ ๊ทธ๋๋ก ๋๋ฌ๋ฉ๋๋ค. ๊ฒ์ ์์ง์ ๋งค ํ๋ ์ ์บ์ ํจ์จ์ด ์ค์ํ๋ฐ list ๋
ธ๋ ๋ถ์ฐ์ ์ ํฉํ์ง ์์ผ๋๊น์.
์ฐจ์ด์ ์์ฝ
- ์ธ๋ฆฌ์ผ์
std::list::sort๊ฐ์ ์ฐ๊ฒฐ ๋ฆฌ์คํธ ์ ์ฉ ์ ๋ ฌ์ ์ง์ํ์ง ์์ โ ์ ๋ ฌ์ด ํ์ํ ์ปฌ๋ ์ ์TArray์ฌ์ฉ Sort()๋ฉค๋ฒ ํจ์์Algo::Sort()๋ ๋ค ์กด์ฌํ์ง๋ง ๋ฉค๋ฒ ํจ์๊ฐ ์ปจ๋ฒค์ TArray::Sort()๋ stable์ด ์๋, ์์ ์ ๋ ฌ์ด ํ์ํ๋ฉด ๋ช ์์ ์ผ๋กStableSort()
11. ๊ผฌ๋ฆฌ์ง๋ฌธ ์์ ๊ฒฝ๋ก
Q1. โ์ std::sort๋ RandomAccessIterator๋ฅผ ์๊ตฌํ๋์? ๊ทธ๋ฅ ๋ค ๋ฐ๊ฒ ๋ง๋ค๋ฉด ์ ๋๋์?โ
introsort์ ํต์ฌ์ธ quicksort partition์ด ๋ฌด์์ ์ ๊ทผ์ ์์กดํ๊ธฐ ๋๋ฌธ์ ๋๋ค. mid pivot ์ ํ, ์ ๋์์ ๋ง๋๋ swap, ์ฌ๊ท ๋ถํ ์ ๋ถ๋ถ ๊ตฌ๊ฐ ์ธ๋ฑ์ฑ์ด ๋ชจ๋
it + n์ด๋it - it๊ฐ์ random access ์ฐ์ฐ์ ์๋๋ค. ForwardIterator๋ก ๋ง๋ค๋ฉด ์ด ์ฐ์ฐ๋ค์ดO(n)์ด ๋์ด quicksort ์์ฒด๊ฐO(nยฒ)์ผ๋ก ๋จ์ด์ง๋๋ค. ๊ทธ๋์ RandomAccess ์ปจํ ์ด๋์ฉ ๋น ๋ฅธ ์ ๋ ฌ์ ์๊ณ ๋ฆฌ์ฆ์ผ๋ก, ์ฐ๊ฒฐ ๋ฆฌ์คํธ์ฉ ๋ณํฉ ์ ๋ ฌ (merge sort)์ ๋ฉค๋ฒ ํจ์๋ก ๋ถ๋ฆฌํ ๊ฒ STL์ ์ค๊ณ์ ๋๋ค.
Q2. โlist::sort๋ ์ ๋ณํฉ ์ ๋ ฌ (merge sort)์ ์ฐ๋์? quicksort๋ heapsort๋ ์ ๋๋์?โ
์ฐ๊ฒฐ ๋ฆฌ์คํธ์ ๊ตฌ์กฐ์ ๊ฐ์ฅ ์ ๋ง๋ ์๊ณ ๋ฆฌ์ฆ์ด ๋ณํฉ ์ ๋ ฌ (merge sort)์ด๊ธฐ ๋๋ฌธ์ ๋๋ค. ๋ ์ ๋ ฌ ๋ฆฌ์คํธ์ merge๊ฐ ํฌ์ธํฐ ์ฌ์ฐ๊ฒฐ๋ง์ผ๋ก O(n) in-place๋ก ๋๋ฉ๋๋ค. quicksort๋ partition์ ๋ฌด์์ ์ ๊ทผ์ด ํ์ํด list์์ ๋นํจ์จ์ ์ด๊ณ , heapsort๋ ๋ง์ฐฌ๊ฐ์ง๋ก ๋ฌด์์ ์ ๊ทผ ๊ธฐ๋ฐ ์๋ฃ๊ตฌ์กฐ(heap)๊ฐ ํ์ํฉ๋๋ค. ๋ณํฉ ์ ๋ ฌ (merge sort)๋ ์์ฐจ ์ ๊ทผ๋ง์ผ๋ก ๋์ํ๊ณ ์์ ์ฑ๋ ์์ฐ์ค๋ฝ๊ฒ ๋ฐ๋ผ์ต๋๋ค. ๋ํด์ ํ์ค์
list::sort์ stable + O(n log n) ๋ณด์ฅ์ ์๊ตฌํ๋๋ฐ ์ด๊ฑธ ๋ง์กฑํ๋ ๊ฒ ์ฌ์ค์ ๋ณํฉ ์ ๋ ฌ (merge sort)์ ๋๋ค.
Q3. โ๋ ๋ค O(n log n)์ธ๋ฐ ์ค์ ๋ก ์ด๋ค ์ฐจ์ด๊ฐ ์๋์?โ
์ด๋ก ๋ณต์ก๋๋ ๊ฐ์ง๋ง ์ค์ธก ๋น์ฉ ๊ตฌ์กฐ๊ฐ ๋ค๋ฆ ๋๋ค. ์ฒซ์งธ, ๋ฐ์ดํฐ ์ด๋ ๋น์ฉ์ ๋๋ค.
std::sort๋ partitionยทmerge ๊ณผ์ ์์ ๊ฐ์ฒด ์์ฒด๋ฅผ swapํฉ๋๋ค. ํฐ ๊ฐ์ฒด๋ฅผ ๋ด์ ์ปจํ ์ด๋๋ผ๋ฉด ๋งค swap๋ง๋ค memcpy๋ move ์์ฑ์๊ฐ ํธ์ถ๋ฉ๋๋ค.list::sort๋ prev/next ํฌ์ธํฐ ๋ ๊ฐ๋ง ์ฌ๋ฐฐ์นํ๋ ๊ฐ์ฒด๋ ํ ๋ฒ๋ ์ ์ฎ๊น๋๋ค. ๋์งธ, ์บ์ ์นํ์ฑ์ ์ ๋ฐ๋๋ก vector๊ฐ ์๋์ ์ ๋๋ค. ์ ์งธ, iterator ์์ ์ฑ์ list๊ฐ ์ฐ์์ ๋๋ค. ๊ทธ๋์ ํฐ ๊ฐ์ฒด + ์์ฃผ ์ ๋ ฌ + ์์ ์ฑ ํ์ ์ผ์ด์ค์์ list๊ฐ, ์ผ๋ฐ์ ์ธ ๊ฒฝ์ฐ์ vector + sort๊ฐ ์ ๋ต์ ๋๋ค.
Q4. โlist::sort๋ stable์ธ๋ฐ std::sort๋ unstable์ธ ์ด์ ๋?โ
์๊ณ ๋ฆฌ์ฆ ์ฐจ์ด์ ๋๋ค. ๋ณํฉ ์ ๋ ฌ (merge sort)๋ ์์ฐ์ค๋ฝ๊ฒ stable์ ๋๋ค โ merge ๋จ๊ณ์์ ๋๋ฑํ ์์๋ฉด ์ผ์ชฝ(์์ชฝ) ๊ฒ์ ๋จผ์ ์ ํํ๋๋ก
<๋ง ์ฐ๊ณ<=๋ฅผ ์ ์ฐ๋ฉด ์๋์ผ๋ก ์์ ์ฑ์ด ์ ์ง๋ฉ๋๋ค. ๋ฐ๋ฉด quicksort์ partition์ pivot ์ข์ฐ๋ก ์์๋ฅผ swapํ๋ ๊ณผ์ ์์ ๋๋ฑ ์์์ ์๋ ์์๊ฐ ๊นจ์ง๋๋ค. ๊ทธ๋์ introsort ์ ์ฒด๋ก ๋ดค์ ๋std::sort๋ stable์ ๋ณด์ฅํ ์ ์์ต๋๋ค. ์์ ์ฑ์ด ํ์ํ๋ฉดstd::stable_sort๋ฅผ ์ฐ๋ฉด ๋๋๋ฐ, ์ด๊ฑด ์ถ๊ฐ ๋ฉ๋ชจ๋ฆฌO(n)์ด ํ์ํ๊ฑฐ๋ ๋ฉ๋ชจ๋ฆฌ๋ฅผ ๋ชป ์ก์ ๋ ์๊ฐ์ดO(n logยฒ n)๋ก ๋จ์ด์ง๋๋ค.
Q5. โforward_list์๋ sort๊ฐ ๋ฐ๋ก ์๋์?โ
๋ค,
std::forward_list::sort()๊ฐ ๋ฉค๋ฒ ํจ์๋ก ๋ฐ๋ก ์์ต๋๋ค. forward_list๋ ForwardIterator๋ง ์ง์ํด์--it๋ ์ ๋๋ list๋ณด๋ค ๋ ์ ์ฝ์ด ํฝ๋๋ค. ๊ทธ๋์ ์ธ๋ถ ์๊ณ ๋ฆฌ์ฆ์ด ์๋ ์๊ฐ ์๊ณ , ๋จ๋ฐฉํฅ ์ฐ๊ฒฐ ๋ฆฌ์คํธ์ ๊ตฌ์กฐ๋ฅผ ํ์ฉํ ๋ณํฉ ์ ๋ ฌ (merge sort)๋ฅผ ๋ฉค๋ฒ๋ก ์ ๊ณตํ๋ ๊ฒ ์ ์ผํ ๋ฐฉ๋ฒ์ ๋๋ค. ๊ฐ์ ์ด์ ๋กmerge,splice_after,unique,reverse๊ฐ์ ์ฐ์ฐ๋ ๋ชจ๋ ๋ฉค๋ฒ ํจ์๋ก ์์ต๋๋ค.
Q6. โset์ด๋ map์ ์ ๋ ฌ๋ ์ํ๋ก ์ ์ง๋๋๋ฐ sort ๋ฉค๋ฒ ํจ์๊ฐ ์๋ ์ด์ ๋?โ
์๋ฃ๊ตฌ์กฐ ์์ฒด๊ฐ ์ฝ์ ์์ ์ ์ด๋ฏธ ์ ๋ ฌ์ ์ ์งํ๊ธฐ ๋๋ฌธ์ ๋๋ค.
std::set๊ณผstd::map์ RB-Tree ๊ธฐ๋ฐ์ด๊ณ ์ฝ์ ํ ๋ ํธ๋ฆฌ ํ์ ๊ณผ ์ฌ์์น ๋ก ์ ๋ ฌ ๋ถ๋ณ์์ ์ ์งํฉ๋๋ค. ๋ฐ๋ผ์ ๋ณ๋์ sort ํธ์ถ์ด ํ์ ์์ต๋๋ค. ์ด๊ฒ list์์ ๊ฒฐ์ ์ ์ฐจ์ด์ ๋๋ค โ list๋ ์์ ์์๋ก pushํ ์ ์์ผ๋ ์ ๋ ฌ์ด ๋ณ๋ ์ฐ์ฐ์ด์ง๋ง, set/map์ ์ ๋ ฌ ์ํ ์์ฒด๊ฐ ์๋ฃ๊ตฌ์กฐ์ invariant์ ๋๋ค.
Q7. โstd::sort ๋์ std::list::sort๋ฅผ ์ฐ๋ฉด ํญ์ ๋น ๋ฅธ๊ฐ์?โ
์๋๋๋ค. list ์์ฒด๊ฐ vector๋ณด๋ค ๊ฑฐ์ ํญ์ ๋๋ฆฝ๋๋ค. 1M๊ฐ ์ ์ ์ ๋ ฌ ๋ฒค์น๋งํฌ์์
vector::sort๊ฐlist::sort๋ณด๋ค ๋ณดํต 5~10๋ฐฐ ๋น ๋ฆ ๋๋ค. ์บ์ ์นํ์ฑ ๋๋ฌธ์ ๋๋ค. list๊ฐ ์ ๋นํ๋๋ ์ผ์ด์ค๋ 13๋ฒ์์ ์ ๋ฆฌํ ๊ทธ๋๋ก โ ๋งค์ฐ ํฐ ๊ฐ์ฒด + ์ฆ์ splice/merge + iterator ์์ ์ฑ ์ ๋ ํ์. ํ๋ฒํ ์ ๋ ฌ ์ํฌ๋ก๋๋ฉด vector + std::sort๊ฐ ์์น์ ๋๋ค. โlist::sort๊ฐ ๋ฐ๋ก ์๋คโ๋ ์ฌ์ค์ list๋ฅผ ์จ์ผ ํ ๋์ ์ ๋ ฌ ๋ฐฉ๋ฒ์ด์ง, list๋ฅผ ์ธ ์ด์ ๊ฐ ์๋๋๋ค.
Q8. โstable_sort์ list::sort๊ฐ ๋ ๋ค stable์ด๋ฉด ์ฐจ์ด๋?โ
๋์ ์ปจํ ์ด๋๊ฐ ๋ค๋ฆ ๋๋ค.
std::stable_sort๋ RandomAccessIterator ์ปจํ ์ด๋(vectorยทdequeยทarray)์ฉ ์์ ์ ๋ ฌ์ด๊ณ ,std::list::sort๋ list ์ ์ฉ์ ๋๋ค. ์ถ๊ฐ ๋ฉ๋ชจ๋ฆฌ๋ ๋ค๋ฆ ๋๋ค โstable_sort๋O(n)์ถ๊ฐ ๋ฒํผ๋ฅผ ์๋ํ๊ณ ์คํจํ๋ฉด ์๊ฐ์ดO(n logยฒ n)๋ก ๋จ์ด์ง์ง๋ง,list::sort๋ ๋ ธ๋ ์ฌ์ฐ๊ฒฐ๋ง์ผ๋ก ํญ์O(1)์ถ๊ฐ ๋ฉ๋ชจ๋ฆฌ +O(n log n)์๊ฐ์ ๋ณด์ฅํฉ๋๋ค.
Q9. โ๊ทธ๋ผ list::sort๋ std::stable_sort๋ณด๋ค ๋ฉ๋ชจ๋ฆฌ ํจ์จ์ด ์ข๋ค๋ ๊ฑด๊ฐ์?โ
๋ฉ๋ชจ๋ฆฌ ํจ์จ ์ธก๋ฉด์์๋ ๊ทธ๋ ์ต๋๋ค. ํ์ง๋ง list ์์ฒด๊ฐ ๋ ธ๋๋ง๋ค prev/next ํฌ์ธํฐ 16๋ฐ์ดํธ + ํ ํ ๋น ํค๋๋ฅผ ๊ฐ๊ณ ์์ด ๋ฉ๋ชจ๋ฆฌ ์ด๋์ vector๋ณด๋ค ํจ์ฌ ๋ง์ด ์๋๋ค (13๋ฒ 5์ฅ). ์ ๋ ฌ ์ค ์ถ๊ฐ๋ก ์ฐ๋ ์์ ๋ฉ๋ชจ๋ฆฌ๋ง ์ ์ ๋ฟ์ด๊ณ , ๋ฒ ์ด์ค ๋ฉ๋ชจ๋ฆฌ ํธํฐํ๋ฆฐํธ๋ vector๊ฐ ์์น์ ๋๋ค. ๊ทธ๋์ ๋ฉ๋ชจ๋ฆฌ ํจ์จ์ด๋ผ๋ ๋จ์ด๋ฅผ ์ด๋ป๊ฒ ํด์ํ๋๋์ ๋ฐ๋ผ ๋ต์ด ๋ฌ๋ผ์ง๋๋ค.
Q10. โTLinkedList๋ ์ Sort ๋ฉค๋ฒ ํจ์๊ฐ ์๋์?โ
์ธ๋ฆฌ์ผ์ด ์๋์ ์ผ๋ก ์ฐ๊ฒฐ ๋ฆฌ์คํธ๋ฅผ 1๊ธ ์๋ฃ๊ตฌ์กฐ๋ก ๋ง๋ค์ง ์์๊ธฐ ๋๋ฌธ์ ๋๋ค. ๊ฒ์ ์์ง์ ๋งค ํ๋ ์ ์๋ง ๊ฐ ๊ฐ์ฒด๋ฅผ ์ํํ๋๋ฐ list ๋ ธ๋ ๋ถ์ฐ์ ์บ์ ๋ฏธ์ค๋ก ์ง๊ฒฐ๋ฉ๋๋ค. ๊ทธ๋์ ์ธ๋ฆฌ์ผ์
TArray๋ฅผ 1๊ธ์ผ๋ก ๋๊ณ ,TLinkedList/TDoubleLinkedList๋ ๊ฐ๋ฒผ์ด ํฌํผ๋ก๋ง ์ ๊ณตํฉ๋๋ค. ์ ๋ ฌ์ด ํ์ํ๋ค๋ฉด ๋ณดํตTArray๋ก ๋ณํํ๊ฑฐ๋ ์ง์ merge sort๋ฅผ ๊ตฌํํฉ๋๋ค. ์ด๊ฒ 13๋ฒ์์ ๋ณธ โ์บ์ ์นํ์ฑ ์ฐ์ โ ์ฒ ํ์ ๋ ๋ค๋ฅธ ๋ฐํ์ ๋๋ค.
ํต์ฌ ์์ฝ ์นด๋ (์ฌ๊ฒ์ฌ)
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
std::sort = <algorithm>, RandomAccess ์๊ตฌ, introsort, unstable
๊ฐ์ฒด swap ๋ค์, O(log n) ์ถ๊ฐ ๋ฉ๋ชจ๋ฆฌ, ์บ์ ์นํ
std::list::sort = list ๋ฉค๋ฒ, Bidirectional๋ก OK, ๋ณํฉ ์ ๋ ฌ (merge sort), stable
ํฌ์ธํฐ ์ฌ์ฐ๊ฒฐ๋ง, O(1) ์ถ๊ฐ ๋ฉ๋ชจ๋ฆฌ, iterator ๋ฌดํจํ X
std::forward_list::sort = forward_list ๋ฉค๋ฒ, Forward๋ก OK, ๋ณํฉ ์ ๋ ฌ (merge sort), stable
์ฐจ์ด๊ฐ ์๊ธด ์ด์ 3๊ฐ์ง:
โ iterator ์นดํ
๊ณ ๋ฆฌ โ list iterator๋ RandomAccess ์๋ โ std::sort ์ปดํ์ผ ์๋ฌ
โก ์๊ณ ๋ฆฌ์ฆ ์ ํฉ์ฑ โ quicksort partition์ ๋ฌด์์ ์ ๊ทผ ํ์, list์ ๋ณํฉ ์ ๋ ฌ (merge sort)๊ฐ ์์ฐ
โข ๋น์ฉ ๊ตฌ์กฐ โ list::sort๋ ๋ฐ์ดํฐ ์ด๋ 0 (ํฌ์ธํฐ๋ง), ํฐ ๊ฐ์ฒด์ผ์๋ก ์ด๋ ํผ
๊ฐ์ ํจํด (๋ฉค๋ฒ vs ์๊ณ ๋ฆฌ์ฆ):
set/map::find โ O(log n) โ ์๊ณ ๋ฆฌ์ฆ std::find๋ O(n)
unordered_map::find โ O(1) ํ๊ท
list::merge/splice/unique/reverse โ ๋
ธ๋ ์ฌ์ฐ๊ฒฐ๋ง
์ ๋ ฌ family:
std::stable_sort โ vectorยทdequeยทarray ์ฉ ์์ ์ ๋ ฌ, O(n) ๋ฉ๋ชจ๋ฆฌ ๋๋ O(n logยฒ n) ์๊ฐ
std::partial_sort โ ์์ k๊ฐ๋ง, O(n log k)
std::nth_element โ k๋ฒ์งธ๋ง ์ ์๋ฆฌ, O(n) ํ๊ท
์ธ๋ฆฌ์ผ:
Algo::Sort / TArray::Sort โ std::sort ๋์
Algo::StableSort / TArray::StableSort โ std::stable_sort ๋์
TLinkedList โ Sort ๋ฉค๋ฒ ํจ์ ์์ (1๊ธ X, ์๋ ๊ตฌํ)
ํ์ค ์๊ตฌ:
list::sort โ stable + O(n log n) ๋ณด์ฅ
std::sort โ ํ๊ท /์ต์
O(n log n) ๋ณด์ฅ (introsort ๋๋ถ)
ํ๊ท ๋ค๋ฆฌ โ ๋ค๋ฅธ CS ํ์ผ ์ฐ๊ฒฐ
| ํ์ผ | ์ฐ๊ฒฐ ์ง์ |
|---|---|
| 13_vector_vs_list | ๋ฉ๋ชจ๋ฆฌ ๋ ์ด์์ยท์บ์ ์นํ์ฑ. list๊ฐ ์ ๋นํ๋๋ ์๋๋ฆฌ์ค(ํฐ ๊ฐ์ฒด + splice + iterator ์์ ์ฑ)๊ฐ list::sort์ ๊ฐ์น์ ์ง๊ฒฐ |
| 16_stl_containers | STL ์ปจํ ์ด๋ ์นดํ ๊ณ ๋ฆฌ ์ ๋ฆฌ. forward_list / list / vector iterator ์นดํ ๊ณ ๋ฆฌ ํ |
| 17_find_vs_binary_search | 9-1 iterator ์นดํ ๊ณ ๋ฆฌ(Input โ Forward โ Bidirectional โ RandomAccess), ๋ฉค๋ฒ vs ์๊ณ ๋ฆฌ์ฆ ์ปจ๋ฒค์ . ์ด๋ฒ 18๋ฒ์ด ๊ทธ ์ปจ๋ฒค์ ์ ์ ๋ ฌ ๋ฒ์ |
| 15_pushback_vs_emplaceback | move ์์ฑ์ยท๊ฐ์ฒด ์ด๋ ๋น์ฉ. list::sort๊ฐ โ๋ฐ์ดํฐ ์ด๋ 0โ์ผ๋ก ํํผํ๋ ๋น์ฉ์ ์ ์ฒด |
| 14_std_map | RB-Tree ์๋ฃ๊ตฌ์กฐ์ invariant ์ ์ง(set/map์ ์ ๋ ฌ ๋ฉค๋ฒ๊ฐ ๋ถํ์ํ ์ด์ ). list์์ ๋๋น |