Namespaces
Variants

std::partial_sort

ja.cppreference.net より
 
 
アルゴリズムライブラリ
制約付きアルゴリズムとレンジのアルゴリズム (C++20)
制約付きアルゴリズム、例えば ranges::copy、ranges::sort、...
変更を行わないシーケンス操作    
一括操作
(C++17)
検索操作
変更を行うシーケンス操作
コピー操作
(C++11)
(C++11)
スワップ操作
変換操作
生成操作
削除操作
順序変更操作
(C++17まで)(C++11)
(C++20)(C++20)
サンプリング操作
(C++17)

ソートと関連操作
分割操作
(C++11)    

ソート操作
二分探索操作
(分割された範囲に対する)
集合操作 (ソート済み範囲に対する)
マージ操作 (ソート済み範囲に対する)
ヒープ操作
最小値/最大値操作
(C++11)
(C++17)
辞書式比較操作
置換操作


 
ヘッダ <algorithm>
template< class RandomIt >
void partial_sort( RandomIt first, RandomIt middle, RandomIt last );
で定義 (1) (C++20以上constexpr)
template< class ExecutionPolicy, class RandomIt >
void partial_sort( ExecutionPolicy&& policy,
                   RandomIt first, RandomIt middle, RandomIt last );
(2) (C++17以上)
template< class RandomIt, class Compare >
void partial_sort( RandomIt first, RandomIt middle, RandomIt last,
                   Compare comp );
(3) (C++20以上constexpr)
template< class ExecutionPolicy, class RandomIt, class Compare >
void partial_sort( ExecutionPolicy&& policy,
                   RandomIt first, RandomIt middle, RandomIt last,
                   Compare comp );
(4) (C++17以上)

範囲 [first, middle) 内の要素を、範囲 middle − first が [first, last) 内の最小の要素をソート済みで含むように並べ替えます。

等しい要素の順序は保持されるとは限りません。範囲 [middle, last) 内の残りの要素の順序は未規定です。

1) 要素は ソート に関して operator<(C++20まで)std::less{}(C++20以上)されます。
3) 要素は comp に関してソートされます。
2,4) (1,3) と同じですが、policy に従って実行されます。
これらのオーバーロードは、次の式の値が true である場合にのみオーバーロード解決に参加します:

std::is_execution_policy_v<std::decay_t<ExecutionPolicy>>

(C++20まで)

std::is_execution_policy_v<std::remove_cvref_t<ExecutionPolicy>>

(C++20以上)

以下の条件のいずれかを満たす場合、動作は未定義です:

  • [first, middle)RandomIt は ValueSwappable の要件を満たさなければなりません。 [middle, last) または が有効な範囲
  • ではありません。*first*first の型は Swappable ではありません。
(C++11まで)

パラメータ

first, last - 要素を並べ替える範囲を定義するイテレータのペア
middle - 範囲 [ first , middle ) がソートされた要素を含む
policy - 使用する実行ポリシー
comp - 比較関数オブジェクト(つまり Compare の要件を満たすオブジェクト)。最初の引数が2番目の引数より 小さい (つまり 前に順序付けられる )場合に​ true を返す。

比較関数のシグネチャは以下と同等であるべき:

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

シグネチャが const & を持つ必要はないが、関数は渡されたオブジェクトを変更してはならず、 値カテゴリ に関係なく型(おそらくconst) Type1 と Type2 のすべての値を受け入れられなければならない(したがって、 Type1& は許可されない 、 Type1 も Type1 に対してムーブがコピーと等価でない限り許可されない (C++11以降) )。
型 Type1 と Type2 は、 RandomIt 型のオブジェクトが間接参照され、それら両方に暗黙的に変換可能でなければならない。 ​

型要件
-
RandomIt は LegacyRandomAccessIterator の要件を満たさなければならない。
-
Compare は Compare の要件を満たさなければならない。

計算量

M を middle - first として、 N を last - first として与えられる:

1,2) およそ N·log(M) 回の比較を operator < (C++20まで) std:: less { } (C++20以降) を用いて行う。
3,4) 約 N·log(M) 回の比較子 comp の適用。

例外

ExecutionPolicyという名前のテンプレートパラメータを持つオーバーロードは、 以下のようにエラーを報告します:

  • アルゴリズムの一部として呼び出された関数の実行が例外をスローした場合、 ExecutionPolicy が 標準ポリシー のいずれかであるとき、 std::terminate が呼び出される。それ以外の ExecutionPolicy については、動作は実装定義である。
  • アルゴリズムがメモリの確保に失敗した場合、 std::bad_alloc がスローされる。

実装例

実装については libstdc++ および libc++ も参照してください。

partial_sort (1)
template<typename RandomIt>
constexpr //< since C++20
void partial_sort(RandomIt first, RandomIt middle, RandomIt last)
{
    typedef typename std::iterator_traits<RandomIt>::value_type VT;
    std::partial_sort(first, middle, last, std::less<VT>());
}
partial_sort (3)
namespace impl
{
    template<typename RandomIt, typename Compare>
    constexpr //< since C++20
    void sift_down(RandomIt first, RandomIt last, const Compare& comp)
    {
        // sift down element at “first”
        const auto length = static_cast<std::size_t>(last - first);
        std::size_t current = 0;
        std::size_t next = 2;
        while (next < length)
        {
            if (comp(*(first + next), *(first + (next - 1))))
                --next;
            if (!comp(*(first + current), *(first + next)))
                return;
            std::iter_swap(first + current, first + next);
            current = next;
            next = 2 * current + 2;
        }
        --next;
        if (next < length && comp(*(first + current), *(first + next)))
            std::iter_swap(first + current, first + next);
    }
    template<typename RandomIt, typename Compare>
    constexpr //< since C++20
    void heap_select(RandomIt first, RandomIt middle, RandomIt last, const Compare& comp)
    {
        std::make_heap(first, middle, comp);
        for (auto i = middle; i != last; ++i)
        {
            if (comp(*i, *first))
            {
                std::iter_swap(first, i);
                sift_down(first, middle, comp);
            }
        }
    }
} // namespace impl
template<typename RandomIt, typename Compare>
constexpr //< since C++20
void partial_sort(RandomIt first, RandomIt middle, RandomIt last, Compare comp)
{
    impl::heap_select(first, middle, last, comp);
    std::sort_heap(first, middle, comp);
}

注記

アルゴリズム

使用されるアルゴリズムは通常、最小要素を選択するために heap select が使用され、ヒープ内の選択された要素を昇順でソートするために heap sort が使用されます。

要素を選択するために、ヒープが使用されます( ヒープ を参照)。例えば、 operator < を比較関数として使用する場合、 最大ヒープ が middle − first 個の最小要素を選択するために使用されます。

ヒープソート は選択後に [ first , middle ) で選択された要素をソートするために使用されます( std::sort_heap を参照)。

使用目的

std::partial_sort アルゴリズムは、 小さな定数個 の [ first , middle ) の選択要素に対して使用されることを意図しています。

例

#include <algorithm>
#include <array>
#include <functional>
#include <iostream>
void print(const auto& s, int middle)
{
    for (int a : s)
        std::cout << a << ' ';
    std::cout << '\n';
    if (middle > 0)
    {
        while (middle-- > 0)
            std::cout << "--";
        std::cout << '^';
    }
    else if (middle < 0)
    {
        for (auto i = s.size() + middle; --i; std::cout << "  ")
        {}
        for (std::cout << '^'; middle++ < 0; std::cout << "--")
        {}
    }
    std::cout << '\n';
};
int main()
{
    std::array<int, 10> s{5, 7, 4, 2, 8, 6, 1, 9, 0, 3};
    print(s, 0);
    std::partial_sort(s.begin(), s.begin() + 3, s.end());
    print(s, 3);
    std::partial_sort(s.rbegin(), s.rbegin() + 4, s.rend());
    print(s, -4);
    std::partial_sort(s.rbegin(), s.rbegin() + 5, s.rend(), std::greater{});
    print(s, -5);
}

出力例:

5 7 4 2 8 6 1 9 0 3
0 1 2 7 8 6 5 9 4 3
------^
4 5 6 7 8 9 3 2 1 0
          ^--------
4 3 2 1 0 5 6 7 8 9
        ^----------

不具合報告

以下の動作変更の欠陥報告書は、以前に公開されたC++規格に対して遡及的に適用されました。

DR 適用対象 公開時の動作 正しい動作
P0896R4 C++98 [ first , middle ) および [ middle , last )
が有効な範囲であることが要求されていなかった
いずれかが無効な場合
動作は未定義となる

関連項目

範囲がソートされていた場合のN番目の要素を見つける
(関数テンプレート & アルゴリズム関数オブジェクト)
範囲の要素をコピーして部分的にソートする
(関数テンプレート & アルゴリズム関数オブジェクト)
等価な要素間の相対順序を保ちながら要素の範囲をソートする
(関数テンプレート & アルゴリズム関数オブジェクト)
要素の範囲をソートする
(関数テンプレート & アルゴリズム関数オブジェクト)
範囲の最初のN個の要素をソートする
(アルゴリズム関数オブジェクト)