Namespaces
Variants

std:: nth_element

From cppreference.net
Algorithm library
Constrained algorithms and algorithms on ranges (C++20)
Constrained algorithms, e.g. ranges::copy , ranges::sort , ...
Execution policies (C++17)
Non-modifying sequence operations
Batch operations
(C++17)
Search operations
Modifying sequence operations
Copy operations
(C++11)
(C++11)
Swap operations
Transformation operations
Generation operations
Removing operations
Order-changing operations
(until C++17) (C++11)
(C++20) (C++20)
Sampling operations
(C++17)

Sorting and related operations
Partitioning operations
Sorting operations
(C++11)
nth_element

Binary search operations
(on partitioned ranges)
Set operations (on sorted ranges)
Merge operations (on sorted ranges)
Heap operations
Minimum/maximum operations
Lexicographical comparison operations
Permutation operations
C library
Numeric operations
Operations on uninitialized memory
헤더 파일에 정의됨 <algorithm>
template < class RandomIt >
void nth_element ( RandomIt first, RandomIt nth, RandomIt last ) ;
(1) (C++20부터 constexpr)
template < class ExecutionPolicy, class RandomIt >

void nth_element ( ExecutionPolicy && policy,

RandomIt first, RandomIt nth, RandomIt last ) ;
(2) (C++17부터)
template < class RandomIt, class Compare >

void nth_element ( RandomIt first, RandomIt nth, RandomIt last,

Compare comp ) ;
(3) (C++20부터 constexpr)
template < class ExecutionPolicy, class RandomIt, class Compare >

void nth_element ( ExecutionPolicy && policy,
RandomIt first, RandomIt nth, RandomIt last,

Compare comp ) ;
(4) (C++17부터)

nth_element [ first , last ) 범위 내의 요소들을 재배열하여 재배열 후 다음과 같은 상태가 되도록 합니다:

  • nth 가 가리키는 요소는 [ first , last ) 구간이 정렬되었을 때 해당 위치에 오게 될 요소로 변경됩니다.
  • [ first , nth ) 구간의 모든 반복자 i [ nth , last ) 구간의 모든 반복자 j 에 대해 다음 조건이 만족됩니다:
1,2) bool ( * j < * i ) (C++20 이전) std:: less { } ( * j, * i ) (C++20 이후) false 입니다.
3,4) bool ( comp ( * j, * i ) ) false 입니다.


1) 요소들은 가정적으로 정렬된 상태이며, operator < (C++20 이전) std:: less { } (C++20 이후) 에 따라 정렬됩니다.
3) 요소들은 가정적으로 comp 에 따라 정렬된 상태로 가정됩니다.
2,4) (1,3) 와 동일하지만, policy 에 따라 실행됩니다.
다음 모든 조건이 만족될 때만 이 오버로드들이 오버로드 해결에 참여합니다:

std:: is_execution_policy_v < std:: decay_t < ExecutionPolicy >> true 인 경우.

(C++20 이전)

std:: is_execution_policy_v < std:: remove_cvref_t < ExecutionPolicy >> true 인 경우.

(C++20 이후)

다음 조건 중 하나라도 충족되면, 동작은 정의되지 않습니다:

(C++11 이전)
(C++11 이후)

목차

매개변수

first, last - 부분 정렬할 요소들의 범위 를 정의하는 반복자 쌍
nth - 정렬 분할 지점을 정의하는 임의 접근 반복자
policy - 사용할 실행 정책
comp - 비교 함수 객체(즉 Compare 요구 사항을 만족하는 객체)로 첫 번째 인수가 두 번째 인수보다 작은 경우(즉 앞에 오는 경우) ​ true 를 반환함

비교 함수의 시그니처는 다음과 동일해야 함:

bool cmp ( const Type1 & a, const Type2 & b ) ;

시그니처에 const & 가 필요하지는 않지만, 함수는 전달된 객체를 수정해서는 안 되며 값 범주 에 관계없이 Type1 Type2 타입의 모든 값을 받아들일 수 있어야 함(따라서 Type1& 는 허용되지 않으며 , Type1 에 대한 이동이 복사와 동등하지 않는 한 Type1 도 허용되지 않음 (C++11부터) ).
Type1 Type2 타입은 RandomIt 타입의 객체를 역참조한 후 두 타입 모두로 암시적으로 변환 가능해야 함 ​

타입 요구 사항
-
RandomIt LegacyRandomAccessIterator 요구 사항을 충족해야 함
-
Compare Compare 요구 사항을 충족해야 함

복잡도

주어진 N last - first 로:

1) O(N) 비교를 평균적으로 operator < (until C++20) std:: less { } (since C++20) 사용하여 수행합니다.
2) O(N) 비교를 사용하며 operator < (C++20 이전) std:: less { } (C++20 이후) , 그리고 O(N·log(N)) 스왑이 발생합니다.
3) O(N) 비교자 comp 의 평균 적용 횟수.
4) O(N) 비교자 comp 의 적용, 그리고 O(N·log(N)) 교환 연산.

예외

ExecutionPolicy 라는 템플릿 매개변수를 사용하는 오버로드는 다음과 같이 오류를 보고합니다:

  • 알고리즘의 일부로 호출된 함수 실행 중 예외가 발생하고 ExecutionPolicy 표준 정책 중 하나인 경우, std::terminate 가 호출됩니다. 다른 ExecutionPolicy 의 경우 동작은 구현에 따라 정의됩니다.
  • 알고리즘이 메모리 할당에 실패하는 경우, std::bad_alloc 이 throw됩니다.

가능한 구현

다음 구현도 참조하십시오: libstdc++ , libc++ , 그리고 MSVC STL .

참고 사항

사용된 알고리즘은 일반적으로 Introselect 이지만, 적절한 평균 경우 복잡도를 가진 다른 Selection algorithm 도 허용됩니다.

예제

#include <algorithm>
#include <cassert>
#include <functional>
#include <iostream>
#include <numeric>
#include <vector>
void printVec(const std::vector<int>& vec)
{
    std::cout << "v = {";
    for (char sep[]{0, ' ', 0}; const int i : vec)
        std::cout << sep << i, sep[0] = ',';
    std::cout << "};\n";
}
int main()
{
    std::vector<int> v{5, 10, 6, 4, 3, 2, 6, 7, 9, 3};
    printVec(v);
    auto m = v.begin() + v.size() / 2;
    std::nth_element(v.begin(), m, v.end());
    std::cout << "\nThe median is " << v[v.size() / 2] << '\n';
    // N번째 요소 앞/뒤 요소들의 불균등성 결과:
    assert(std::accumulate(v.begin(), m, 0) < std::accumulate(m, v.end(), 0));
    printVec(v);
    // 참고: comp 함수 변경됨
    std::nth_element(v.begin(), v.begin() + 1, v.end(), std::greater{});
    std::cout << "\nThe second largest element is " << v[1] << '\n';
    std::cout << "The largest element is " << v[0] << '\n';
    printVec(v);
}

가능한 출력:

v = {5, 10, 6, 4, 3, 2, 6, 7, 9, 3};
The median is 6
v = {3, 2, 3, 4, 5, 6, 10, 7, 9, 6};
The second largest element is 9
The largest element is 10
v = {10, 9, 6, 7, 6, 3, 5, 4, 3, 2};

결함 보고서

다음의 동작 변경 결함 보고서들은 이전에 발표된 C++ 표준에 소급 적용되었습니다.

DR 적용 대상 게시된 동작 올바른 동작
LWG 2150 C++98 재배열 후, nth 이전의 한 요소만이 nth 이후의 한 요소보다
크지 않아야 한다고 요구됨
요구사항을
수정함
LWG 2163 C++98 오버로드 ( 1 ) 가 요소 비교에 operator > 사용 operator < 로 변경됨
P0896R4 C++98 [ first , nth ) [ nth , last )
가 유효한 범위일 필요가 없었음
둘 중 하나라도 유효하지 않으면
동작이 정의되지 않음

참고 항목

범위에서 가장 큰 요소를 반환합니다
(함수 템플릿)
범위에서 가장 작은 요소를 반환합니다
(함수 템플릿)
요소 범위를 복사하고 부분적으로 정렬합니다
(함수 템플릿)
동일한 요소들 간의 순서를 유지하면서 요소 범위를 정렬합니다
(함수 템플릿)
범위를 오름차순으로 정렬합니다
(함수 템플릿)
주어진 요소로 분할되도록 주어진 범위를 부분적으로 정렬합니다
(알고리즘 함수 객체)