Index: libcxx/benchmarks/CMakeLists.txt =================================================================== --- libcxx/benchmarks/CMakeLists.txt +++ libcxx/benchmarks/CMakeLists.txt @@ -162,6 +162,7 @@ algorithms/make_heap.bench.cpp algorithms/make_heap_then_sort_heap.bench.cpp algorithms/min_max_element.bench.cpp + algorithms/nth_element.bench.cpp algorithms/pop_heap.bench.cpp algorithms/push_heap.bench.cpp algorithms/ranges_make_heap.bench.cpp Index: libcxx/include/__algorithm/nth_element.h =================================================================== --- libcxx/include/__algorithm/nth_element.h +++ libcxx/include/__algorithm/nth_element.h @@ -12,6 +12,7 @@ #include <__algorithm/comp.h> #include <__algorithm/comp_ref_type.h> #include <__algorithm/iterator_operations.h> +#include <__algorithm/min_element.h> #include <__algorithm/sort.h> #include <__config> #include <__debug> @@ -25,6 +26,25 @@ _LIBCPP_BEGIN_NAMESPACE_STD +// Implement partial sort base on selection sort. Rearranges elements such that the range [__first, __middle) contains +// the sorted __middle − __first smallest elements in the range [first, last). +// For selection sort, after each round, the position of element that __first represents is determined. That is, if we +// end up when __first == __middle, [__first, __middle) contains the sorted __middle − __first smallest elements in the +// range [first, last) already. +template +_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 void __selection_partial_sort( + _BidirectionalIterator __first, _BidirectionalIterator __middle, _BidirectionalIterator __last, _Compare __comp) { + // if [__first, __last - 1) is determined, then [__first, __last) is determined. + if (__middle == __last) + --__middle; + + for (; __first != __middle; ++__first) { + _BidirectionalIterator __i = std::__min_element(__first, __last, __comp); + if (__i != __first) + _IterOps<_AlgPolicy>::iter_swap(__first, __i); + } +} + template _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 bool __nth_element_find_guard(_RandomAccessIterator& __i, _RandomAccessIterator& __j, @@ -73,7 +93,8 @@ } if (__len <= __limit) { - std::__selection_sort<_AlgPolicy, _Compare>(__first, __last, __comp); + std::__selection_partial_sort<_AlgPolicy, _Compare>(__first, __nth + difference_type(1), __last, __comp); + // [__first, __nth) <= *__nth and *__nth <= (__nth, __last) return; } // __len > __limit >= 3