Namespaces
Variants

std::ranges::partition

cppreference.netより
 
 
アルゴリズムライブラリ
制約付きアルゴリズムと範囲アルゴリズム (C++20)
制約付きアルゴリズム、例: ranges::copy, ranges::sort, ...
ソートおよび関連操作
分割操作
(C++11)    

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


 
制約付きアルゴリズム
このメニューのすべての名前は名前空間に属しますstd::ranges
非変更シーケンス操作
変更シーケンス操作
分割操作
ソート操作
二分探索操作(ソート済み範囲に対する)
       
       
集合操作(ソート済み範囲に対する)
ヒープ操作
最小/最大操作
       
       
順列操作
畳み込み操作
数値操作
(C++23)            
未初期化ストレージに対する操作
戻り値の型
 
ヘッダで定義<algorithm>
呼び出しシグネチャ
template< std::permutable I, std::sentinel_for<I> S, class Proj = std::identity,
          std::indirect_unary_predicate<std::projected<I, Proj>> Pred >
constexpr ranges::subrange<I>
    partition( I first, S last, Pred pred, Proj proj = {} );
(1) (C++20以降)
template< ranges::forward_range R, class Proj = std::identity,
          std::indirect_unary_predicate<
              std::projected<ranges::iterator_t<R>, Proj>> Pred >
requires std::permutable<ranges::iterator_t<R>>
constexpr ranges::borrowed_subrange_t<R>
    partition( R&& r, Pred pred, Proj proj = {} );
(2) (C++20以降)
1) 範囲 [first, last) 内の要素を並べ替え、射影 [first, last) のすべての要素のうち、述語 proj が pred を返すものが、述語 true が proj を返す要素の射影 pred よりも前に来るようにします。要素の相対順序は保持されません。false2)
(1) と同様ですが、 をソース範囲として使用し、(1) を r として、ranges::begin(r) を first として使用するかのように動作します。ranges::end(r) および last を使用します。

このページで説明されている関数のようなエンティティは アルゴリズム関数オブジェクト (非公式には niebloid として知られています) であり、次のとおりです:

  • それらのいずれかを呼び出すときに明示的なテンプレート引数リストを指定することはできません。
  • それらは 引数依存の名前検索 には表示されません。
  • それらのいずれかが 通常の非修飾名検索 によって関数呼び出し演算子の左側の名前として見つかった場合、引数依存の名前検索 は抑制されます。

パラメータ

first, last - 要素を並べ替える範囲を定義する イテレータ-番兵 のペア
r - 並べ替える要素の範囲
pred - 投影された要素に適用する述語
proj - 要素に適用する投影

戻り値

第2のグループの最初の要素を指すイテレータで始まり、 last と等しいイテレータで終わる部分範囲。 (2) は r が非 borrowed_range 型の右辺値である場合、 std::ranges::dangling を返す。

計算量

N = ranges:: distance ( first, last ) が与えられたとき、述語と射影の適用は正確に N 回実行される。 I が ranges::bidirectional_iterator をモデルする場合、最大 N / 2 回の交換が行われ、それ以外の場合は最大 N 回の交換が行われる。

実装例

struct partition_fn
{
    template<std::permutable I, std::sentinel_for<I> S, class Proj = std::identity,
             std::indirect_unary_predicate<std::projected<I, Proj>> Pred>
    constexpr ranges::subrange<I>
        operator()(I first, S last, Pred pred, Proj proj = {}) const
    {
        first = ranges::find_if_not(first, last, std::ref(pred), std::ref(proj));
        if (first == last)
            return {first, first};
        for (auto i = ranges::next(first); i != last; ++i)
        {
            if (std::invoke(pred, std::invoke(proj, *i)))
            {
                ranges::iter_swap(i, first);
                ++first;
            }
        }
        return {std::move(first), std::move(last)};
    }
    template<ranges::forward_range R, class Proj = std::identity,
             std::indirect_unary_predicate<
                 std::projected<ranges::iterator_t<R>, Proj>> Pred>
    requires std::permutable<ranges::iterator_t<R>>
    constexpr ranges::borrowed_subrange_t<R>
        operator()(R&& r, Pred pred, Proj proj = {}) const
    {
        return (*this)(ranges::begin(r), ranges::end(r),
                       std::ref(pred), std::ref(proj));
    }
};
inline constexpr partition_fn partition;

例

#include <algorithm>
#include <forward_list>
#include <functional>
#include <iostream>
#include <iterator>
#include <ranges>
#include <vector>
namespace ranges = std::ranges;
template<class I, std::sentinel_for<I> S, class Cmp = ranges::less>
requires std::sortable<I, Cmp>
void quicksort(I first, S last, Cmp cmp = Cmp {})
{
    using reference = std::iter_reference_t<I>;
    if (first == last)
        return;
    auto size = ranges::distance(first, last);
    auto pivot = ranges::next(first, size - 1);
    ranges::iter_swap(pivot, ranges::next(first, size / 2));
    auto tail = ranges::partition(first, pivot, [=](reference em)
    {
        return std::invoke(cmp, em, *pivot); // em < pivot
    });
    ranges::iter_swap(pivot, tail.begin());
    quicksort(first, tail.begin(), std::ref(cmp));
    quicksort(ranges::next(tail.begin()), last, std::ref(cmp));
}
int main()
{
    std::ostream_iterator<int> cout {std::cout, " "};
    std::vector<int> v {0, 1, 2, 3, 4, 5, 6, 7, 8, 9};
    std::cout << "元のベクトル:  \t";
    ranges::copy(v, cout);
    auto tail = ranges::partition(v, [](int i) { return i % 2 == 0; });
    std::cout << "\n分割済みベクトル: \t";
    ranges::copy(ranges::begin(v), ranges::begin(tail), cout);
    std::cout << "│ ";
    ranges::copy(tail, cout);
    std::forward_list

(注:指示に従い、HTMLタグ・属性は翻訳せず、C++固有用語も保持しました。表示内容は元のまま維持されています)<int> fl {1, 30, -4, 3, 5, -4, 1, 6, -8, 2, -5, 64, 1, 92};
    std::cout << "\n未ソートリスト: \t\t";
    ranges::copy(fl, cout);
    quicksort(ranges::begin(fl), ranges::end(fl), ranges::greater {});
    std::cout << "\nクイックソート済みリスト: \t";
    ranges::copy(fl, cout);
    std::cout << '\n';
}

出力例:

元のベクトル:        0 1 2 3 4 5 6 7 8 9
分割されたベクトル: 0 8 2 6 4 │ 5 3 7 1 9
未ソートリスト:     1 30 -4 3 5 -4 1 6 -8 2 -5 64 1 92
クイックソート済みリスト: 92 64 30 6 5 3 2 1 1 1 -4 -4 -5 -8

関連項目

要素を2つのグループに分割しながら範囲をコピーする
(アルゴリズム関数オブジェクト)
指定された述語によって範囲が分割されているか判定する
(アルゴリズム関数オブジェクト)
各グループ内の相対的な順序を保持しながら要素を2つのグループに分割する
(アルゴリズム関数オブジェクト)
要素の範囲を2つのグループに分割する
(関数テンプレート)