본문 바로가기
이론/알고리즘

introsort 링크 & 고민

by hirudev 2022. 2. 4.

https://en.wikipedia.org/wiki/Introsort

 

Quicksort 로 시작해서 원소들의 길이의 로그값을 기준으로 잡아 기준값에 도달하면 Heapsort 로 전환하고

정렬할 원소들의 수가 어떠한 임계값보다 적을 경우 Insertsort 로 전환한다.

 

GNU Standard C++ Library 의 경우, Heapsort 로 전환할 기준값을 2*Log(n) 로 두고

임계값이 16개 이하가 되면 Insertsort 로 전환한다.

(라고 적혀있어서 소스를 살펴보았다)

 

https://gcc.gnu.org/onlinedocs/libstdc++/libstdc++-html-USERS-4.4/a01347.html#l05207

 

에서 sort 소스를 따라가면 아래와 같이 찾아볼 수 있는데

05205   template<typename _RandomAccessIterator>
05206     inline void
05207     sort(_RandomAccessIterator __first, _RandomAccessIterator __last)
05208     {
05209       typedef typename iterator_traits<_RandomAccessIterator>::value_type
05210     _ValueType;
05211 
05212       // concept requirements
05213       __glibcxx_function_requires(_Mutable_RandomAccessIteratorConcept<
05214         _RandomAccessIterator>)
05215       __glibcxx_function_requires(_LessThanComparableConcept<_ValueType>)
05216       __glibcxx_requires_valid_range(__first, __last);
05217 
05218       if (__first != __last)
05219     {
05220       std::__introsort_loop(__first, __last,
05221                 std::__lg(__last - __first) * 2);
05222       std::__final_insertion_sort(__first, __last);
05223     }
05224     }
05225 

std::__introsort_loop 을 따라가면

02243   template<typename _RandomAccessIterator, typename _Size>
02244     void
02245     __introsort_loop(_RandomAccessIterator __first,
02246              _RandomAccessIterator __last,
02247              _Size __depth_limit)
02248     {
02249       typedef typename iterator_traits<_RandomAccessIterator>::value_type
02250     _ValueType;
02251 
02252       while (__last - __first > int(_S_threshold))
02253     {
02254       if (__depth_limit == 0)
02255         {
02256           _GLIBCXX_STD_P::partial_sort(__first, __last, __last);
02257           return;
02258         }
02259       --__depth_limit;
02260       _RandomAccessIterator __cut =
02261         std::__unguarded_partition(__first, __last,
02262                        _ValueType(std::__median(*__first,
02263                                 *(__first
02264                                   + (__last
02265                                      - __first)
02266                                   / 2),
02267                                 *(__last
02268                                   - 1))));
02269       std::__introsort_loop(__cut, __last, __depth_limit);
02270       __last = __cut;
02271     }
02272     }

위와 같이 나오는데, partial_sort 를 따라가면 기준값이 0이 됐을 경우라 Heapsort 가 진행되고

 

다시, sort() → std::__final_insertion_sort 를 따라가면

02168   enum { _S_threshold = 16 };
02169 
02170   /// This is a helper function for the sort routine.
02171   template<typename _RandomAccessIterator>
02172     void
02173     __final_insertion_sort(_RandomAccessIterator __first,
02174                _RandomAccessIterator __last)
02175     {
02176       if (__last - __first > int(_S_threshold))
02177     {
02178       std::__insertion_sort(__first, __first + int(_S_threshold));
02179       std::__unguarded_insertion_sort(__first + int(_S_threshold), __last);
02180     }
02181       else
02182     std::__insertion_sort(__first, __last);
02183     }

위와 같은 소스를 볼 수 있다.

 

 enum { _S_threshold = 16 };



// __introsort_loop

02252       while (__last - __first > int(_S_threshold))
02253     {
02254       if (__depth_limit == 0)
02255         {
02256           _GLIBCXX_STD_P::partial_sort(__first, __last, __last);
02257           return;
02258         }



// __final_insertion_sort

02176       if (__last - __first > int(_S_threshold))
02177     {
02178       std::__insertion_sort(__first, __first + int(_S_threshold));
02179       std::__unguarded_insertion_sort(__first + int(_S_threshold), __last);
02180     }
02181       else
02182     std::__insertion_sort(__first, __last);
02183     }

 

위 부분이 임계값에 도달했을 때의 부분인데....

 

__introsort_loop 에서 __depth_limit 이 0이 되도 함수에서 빠져나오는 것으로 보아

 

반드시 임계값이 됐을 때 루프에서 빠져나오리라는 보장은 없어보인다.

 

이를 염두해서인지 모르겠는데 __final_insertion_sort 함수에 if (__last - __first > int(_S_threshold)) ~ else 구절에서

 

무조건 삽입정렬을 하는데............................

 

음............ 나중에 구현할 일이 생기면 더 고민해봐야할거 같다.

 

일단, 깊이값을 log(원소 수)*2 으로 두고 quicksort 마냥 깊이 값까지 파티션을 나눠서 힙 정렬

힙정렬이 끝나면 삽입 정렬 정도의 개념으로 기억해둬야겠다.

'이론 > 알고리즘' 카테고리의 다른 글

Optimal binary search tree 링크  (0) 2022.02.04
Timsort - 구현 미정  (0) 2021.05.17

댓글