Namespaces
Variants

std::ranges::stable_sort

From ko.cppreference.net
 
 
Algorithm library
Constrained algorithms and algorithms on ranges (C++20)
Constrained algorithms, e.g. ranges::copy, ranges::sort, ...
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
(C++11)    

Sorting operations
Binary search operations
(on partitioned ranges)
Set operations (on sorted ranges)
Merge operations (on sorted ranges)
Heap operations
Minimum/maximum operations
(C++11)
(C++17)
Lexicographical comparison operations
Permutation operations


 
Constrained algorithms
All names in this menu belong to namespace std::ranges
Non-modifying sequence operations
Modifying sequence operations
Partitioning operations
Sorting operations
Binary search operations (on sorted ranges)
       
       
Set operations (on sorted ranges)
Heap operations
Minimum/maximum operations
       
       
Permutation operations
Fold operations
Numeric operations
(C++23)            
Operations on uninitialized storage
Return types
 
Defined in header <algorithm>
Call signature
template< std::random_access_iterator I, std::sentinel_for<I> S,
          class Comp = ranges::less, class Proj = std::identity >
requires std::sortable<I, Comp, Proj>
    I stable_sort( I first, S last, Comp comp = {}, Proj proj = {} );
(1) (since C++20)
(constexpr since C++26)
template< ranges::random_access_range R, class Comp = ranges::less,
          class Proj = std::identity >
requires std::sortable<ranges::iterator_t<R>, Comp, Proj>
ranges::borrowed_iterator_t<R>
    stable_sort( R&& r, Comp comp = {}, Proj proj = {} );
(2) (since C++20)
(constexpr since C++26)

범위 [first, last)의 요소들을 비내림차순으로 정렬합니다. 동등한 요소들의 순서는 안정적입니다. 즉, 보존됨이 보장됩니다.

시퀀스는 비교기 comp에 대해 정렬되어 있다고 합니다. 만약 시퀀스를 가리키는 임의의 반복자 it와 n이 시퀀스의 요소를 가리키는 유효한 반복자이도록 하는 임의의 음이 아닌 정수 it + n에 대해 std::invoke(comp, std::invoke(proj, *(it + n)), std::invoke(proj, *it)이 false로 평가된다면 그렇습니다.

1) 요소들은 주어진 이진 비교 함수 comp를 사용하여 비교됩니다.
2) (1)과 동일하지만, 범위로 r을 사용하며, ranges::begin(r)을 first로, ranges::end(r)을 last로 사용한 것과 같습니다.

이 페이지에 설명된 함수 유사 개체들은 알고리즘 함수 객체입니다 (비공식적으로 niebloids라고 함). 즉, 다음과 같습니다:

매개변수

first, last - 정렬할 요소들의 범위 를 정의하는 반복자-감시자 쌍
r - 정렬할 범위
comp - 투영된 요소들에 적용할 비교 함수
proj - 요소들에 적용할 투영 함수

반환값

last 와 동일한 반복자.

복잡도

N·log(N) 비교(추가 메모리가 사용 가능한 경우); 여기서 N 은 ranges:: distance ( first, last ) 입니다. N·log²(N) 비교(추가 메모리가 없는 경우). 두 경우 모두 비교 횟수의 두 배에 해당하는 프로젝션 연산이 수행됩니다.

참고 사항

기능 테스트 매크로 값 표준 기능
__cpp_lib_constexpr_algorithms 202306L (C++26) constexpr 안정 정렬

가능한 구현

이 구현은 추가 메모리를 사용할 수 없을 때 사용되는 느린 알고리즘만 보여줍니다. 또한 MSVC STL 와 libstdc++ 의 구현도 참조하십시오.

struct stable_sort_fn
{
    template<std::random_access_iterator I, std::sentinel_for<I> S,
             class Comp = ranges::less, class Proj = std::identity>
    requires std::sortable<I, Comp, Proj>
    constexpr //< C++26부터
    I operator()(I first, S last, Comp comp = {}, Proj proj = {}) const
    {
        auto count = ranges::distance(first, last);
        auto mid = first + count / 2;
        auto last_it = first + count;
        if (count <= 1)
            return last_it;
        (*this)(first, mid, std::ref(comp), std::ref(proj));
        (*this)(mid, last_it, std::ref(comp), std::ref(proj));
        ranges::inplace_merge(first, mid, last_it);
        return last_it;
    }
    template<ranges::random_access_range R, class Comp = ranges::less,
             class Proj = std::identity>
    requires std::sortable<ranges::iterator_t<R>, Comp, Proj>
    constexpr //< C++26부터
    ranges::borrowed_iterator_t<R> operator()(R&& r, Comp comp = {}, Proj proj = {}) const
    {
        return (*this)(ranges::begin(r), ranges::end(r), std::move(comp), std::move(proj));
    }
};
inline constexpr stable_sort_fn stable_sort{};

예제

#include <algorithm>
#include <array>
#include <functional>
#include <iomanip>
#include <iostream>
void print(const auto& seq)
{
    for (const auto& elem : seq)
        std::cout << elem << ' ';
    std::cout << '\n';
}
struct Particle
{
    std::string name; double mass; // MeV
    friend std::ostream& operator<<(std::ostream& os, const Particle& p)
    {
        return os << '\n' << std::left << std::setw(8) << p.name << " : " << p.mass;
    }
};
int main()
{
    std::array s{5, 7, 4, 2, 8, 6, 1, 9, 0, 3};
    // 기본 operator<를 사용하여 정렬
    std::ranges::stable_sort(s);
    print(s);
    // 표준 라이브러리 비교 함수 객체를 사용하여 정렬
    std::ranges::stable_sort(s, std::ranges::greater());
    print(s);
    // 사용자 정의 함수 객체를 사용하여 정렬
    struct
    {
        bool operator()(int a, int b) const { return a < b; }
    } customLess;
    std::ranges::stable_sort(s.begin(), s.end(), customLess);
    print(s);
    // 람다 표현식을 사용하여 정렬
    std::ranges::stable_sort(s, [](int a, int b) { return a > b; });
    print(s);
    // 프로젝션을 사용한 정렬
    Particle particles[]
    {
        {"Electron", 0.511}, {"Muon", 105.66}, {"Tau", 1776.86},
        {"Positron", 0.511}, {"Proton", 938.27}, {"Neutron", 939.57}
    };
    print(particles);
    std::ranges::stable_sort(particles, {}, &Particle::name); //< 이름으로 정렬
    print(particles);
    std::ranges::stable_sort(particles, {}, &Particle::mass); //< 질량으로 정렬
    print(particles);
}

출력:

0 1 2 3 4 5 6 7 8 9
9 8 7 6 5 4 3 2 1 0
0 1 2 3 4 5 6 7 8 9
9 8 7 6 5 4 3 2 1 0
Electron : 0.511
Muon     : 105.66
Tau      : 1776.86
Positron : 0.511
Proton   : 938.27
Neutron  : 939.57
Electron : 0.511
Muon     : 105.66
Neutron  : 939.57
Positron : 0.511
Proton   : 938.27
Tau      : 1776.86
Electron : 0.511
Positron : 0.511
Muon     : 105.66
Proton   : 938.27
Neutron  : 939.57
Tau      : 1776.86

참고 항목

범위의 요소들을 정렬합니다
(알고리즘 함수 객체)
범위의 처음 N개 요소를 정렬합니다
(알고리즘 함수 객체)
요소들을 두 그룹으로 나누되 각 그룹 내에서 상대적 순서를 유지합니다
(알고리즘 함수 객체)
동등한 요소 간의 상대적 순서를 유지하면서 범위의 요소들을 정렬합니다
(함수 템플릿)