概要
範囲のソートやソートされているかの判定を行います。
範囲の指定方法は、
・std::xxx(C++03): 対象の範囲 [first, last) のイテレータ―を指定します。
・std::ranges::xxx(C++20): 対象の範囲 [first, last) のイテレータ―を指定します。
・std::ranges::xxx(C++20): 対象の範囲を直接指定します。
条件判定や、値生成に関数を指定するものがあります。※
std::ranges::xxx(C++20): 射影(projection)関数を指定できるものがあります。※
出力先は、既存の範囲に上書きするものと、別途出力先のイテレーターを指定するものがあります。※
※詳細についてはこちらを参照してください。
https://mappuri.com/program/cpp20-algorithm/
ソート
sort
範囲をソートします。
範囲はランダムに読み書き可能である必要があります。
stable_sort
範囲を安定ソートします。
範囲はランダムアクセスが必要です。
安定ソートでは、同じ値の要素の順序が維持されます。
この例では数値のメンバー変数で比較するので、{3, “a”} と {3, “c”} は同じ値と判断されます。stable_sort ではソート前の順序 {3, “a”}, {3, “c”} がソート後も維持されますが、sort では維持されるとは限りません。
sort, stable_sort のサンプル(C++03)
#include <iostream>
/** r 内の [first, last) の範囲と値を出力 範囲:[0, 9) 値:1 2 3 4 5 4 5 6 6 */
template<class T, class U, class V>
static void output(T&& r, U&& first, V&& last) {
std::cout << "範囲:[" << std::distance(std::begin(r), first) << ", " << std::distance(std::begin(r), last) << ")";
std::cout << " 値:";
std::string delim = "";
for (auto i = first; i != last; ++i, delim = ", ") {
std::cout << delim << *i;
}
std::cout << std::endl;
}
/** r 内の it の位置と値を出力 位置:2 値:3 */
template<class T, class U>
static void output(T&& r, U&& it) {
std::cout << "位置:" << std::distance(std::begin(r), it);
std::cout << " 値:";
if (it == std::end(r) || &*it == nullptr) {
std::cout << "end";
} else {
std::cout << *it;
}
std::cout << std::endl;
}
#include <algorithm>
#include <iostream>
#include <vector>
int main(int argc, char* argv[]) {
{
// 範囲をソートします。(C++03)
std::vector<int> r = { 3, 2, 5, 1, 4 };
std::sort(r.begin(), r.end());
output(r, r.begin(), r.end()); // 範囲:[0, 5) 値:1, 2, 3, 4, 5
}
{
// 範囲をソートします。(C++03)
std::vector<int> r = { 3, 2, 5, 1, 4 };
std::sort(r.begin(), r.end(),
[](int a, int b) { return a > b; }); // 逆順で比較
output(r, r.begin(), r.end()); // 範囲:[0, 5) 値:5, 4, 3, 2, 1
}
{
// 範囲を安定ソートします。(C++03)
std::vector<int> r = { 3, 2, 5, 1, 4 };
std::stable_sort(r.begin(), r.end());
output(r, r.begin(), r.end()); // 範囲:[0, 5) 値:1, 2, 3, 4, 5
}
{
// 範囲を安定ソートします。(C++03)
std::vector<int> r = { 3, 2, 5, 1, 4 };
std::stable_sort(r.begin(), r.end(),
[](int a, int b) { return a > b; }); // 逆順で比較
output(r, r.begin(), r.end()); // 範囲:[0, 5) 値:5, 4, 3, 2, 1
}
return 0;
}
sort, stable_sort のサンプル(C++20 range)
#include <algorithm>
#include <iostream>
#include <vector>
struct S1 {
int intval;
std::string strval;
friend std::ostream& operator<<(std::ostream& os, const S1& s1) {
return os << s1.intval << "," << s1.strval;
}
};
int main(int argc, char* argv[]) {
{
// 範囲をソートします。(C++20)
std::vector<int> r = { 3, 2, 5, 1, 4 };
std::ranges::sort(r);
output(r, r.begin(), r.end()); // 範囲:[0, 5) 値:1, 2, 3, 4, 5
}
{
// 範囲をソートします。(C++20)
std::vector<int> r = { 3, 2, 5, 1, 4 };
std::ranges::sort(r,
[](int a, int b) { return a > b; }); // 逆順で比較
output(r, r.begin(), r.end()); // 範囲:[0, 5) 値:5, 4, 3, 2, 1
}
{
// 範囲をソートします。(C++20)
std::vector<S1> r = { {3, "a"}, {2, "b"}, {3, "c"}, {1, "d"}, {4, "e"} };
std::ranges::sort(r, {}, &S1::intval); // 特定メンバー変数で比較
output(r, r.begin(), r.end()); // 範囲:[0, 5) 値:1,d, 2,b, 3,a, 3,c, 4,e
}
{
// 範囲を安定ソートします。(C++20)
std::vector<int> r = { 3, 2, 5, 1, 4 };
std::ranges::stable_sort(r);
output(r, r.begin(), r.end()); // 範囲:[0, 5) 値:1, 2, 3, 4, 5
}
{
// 範囲を安定ソートします。(C++20)
std::vector<int> r = { 3, 2, 5, 1, 4 };
std::ranges::stable_sort(r,
[](int a, int b) { return a > b; }); // 逆順で比較
output(r, r.begin(), r.end()); // 範囲:[0, 5) 値:5, 4, 3, 2, 1
}
{
// 範囲を安定ソートします。(C++20)
std::vector<S1> r = { {3, "a"}, {2, "b"}, {3, "c"}, {1, "d"}, {4, "e"} };
std::ranges::stable_sort(r, {}, &S1::intval); // 特定メンバー変数で比較
output(r, r.begin(), r.end()); // 範囲:[0, 5) 値:1,d, 2,b, 3,a, 3,c, 4,e
}
return 0;
}
部分ソート
partial_sort
範囲全体をソートした上位が指定位置までの範囲に入るようにソートします。
範囲はランダムアクセスが必要です。
partial_sort_copy
範囲全体をソートした上位が指定位置までの範囲に入るようにソートして出力します。
範囲はランダムアクセスが必要です。
nth_element
範囲の指定位置をソート後の要素にし、それより小さい要素を前に集めます。
範囲はランダムアクセスが必要です。
指定位置以外の要素の順序は不定になります。
partial_sort, partial_sort_copy, nth_element のサンプル(C++03)
#include <algorithm>
#include <iostream>
#include <vector>
int main(int argc, char* argv[]) {
{
// 範囲全体をソートした上位が指定位置までの範囲に入るようにソートします。(C++03)
std::vector<int> r = { 3, 2, 5, 1, 4 };
std::partial_sort(r.begin(), r.begin() + 3, r.end());
output(r, r.begin(), r.end()); // 範囲:[0, 5) 値:1, 2, 3, 5, 4
}
{
// 範囲全体をソートした上位が指定位置までの範囲に入るようにソートして出力します。(C++03)
std::vector<int> r = { 3, 2, 5, 1, 4 };
std::vector<int> o(3);
std::partial_sort_copy(r.begin(), r.end(), o.begin(), o.end());
output(o, o.begin(), o.end()); // 範囲:[0, 3) 値:1, 2, 3
}
{
// 範囲の指定位置をソート後の要素にし、それより小さい要素を前に集めます。(C++03)
std::vector<int> r = { 3, 2, 5, 1, 4 };
std::nth_element(r.begin(), r.begin() + 3, r.end());
output(r, r.begin(), r.end()); // 範囲:[0, 5) 値:2, 1, 3, 4, 5
}
return 0;
}
partial_sort, partial_sort_copy, nth_element のサンプル(C++20 range)
#include <algorithm>
#include <iostream>
#include <vector>
int main(int argc, char* argv[]) {
{
// 範囲全体をソートした上位が指定位置までの範囲に入るようにソートします。(C++20)
std::vector<int> r = { 3, 2, 5, 1, 4 };
std::ranges::partial_sort(r, r.begin() + 3);
output(r, r.begin(), r.end()); // 範囲:[0, 5) 値:1, 2, 3, 5, 4
}
{
// 範囲全体をソートした上位が指定位置までの範囲に入るようにソートして出力します。(C++20)
std::vector<int> r = { 3, 2, 5, 1, 4 };
std::vector<int> o(3);
std::ranges::partial_sort_copy(r, o);
output(o, o.begin(), o.end()); // 範囲:[0, 3) 値:1, 2, 3
}
{
// 範囲の指定位置をソート後の要素にし、それより小さい要素を前に集めます。(C++20)
std::vector<int> r = { 3, 2, 5, 1, 4 };
std::ranges::nth_element(r, r.begin() + 3);
output(r, r.begin(), r.end()); // 範囲:[0, 5) 値:2, 1, 3, 4, 5
}
return 0;
}
ソート判定
is_sorted
範囲がソート済みか判定します。
is_sorted_until
範囲のソートされていない位置を取得します。
is_sorted, is_sorted_until のサンプル(C++11)
#include <algorithm>
#include <iostream>
#include <vector>
int main(int argc, char* argv[]) {
{
// 範囲がソート済みか判定します。(C++11)
std::vector<int> r = { 2, 3, 5, 1, 4 };
bool is_sorted = std::is_sorted(r.begin(), r.end());
std::cout << "is_sorted = " << std::boolalpha << is_sorted << std::endl; // is_sorted = false
}
{
// 範囲のソートされていない位置を取得します。(C++11)
std::vector<int> r = { 2, 3, 5, 1, 4 };
auto is_sorted_until = std::is_sorted_until(r.begin(), r.end());
output(r, is_sorted_until); // 位置:3 値:1
}
return 0;
}
is_sorted, is_sorted_until のサンプル(C++20 range)
#include <algorithm>
#include <iostream>
#include <vector>
int main(int argc, char* argv[]) {
{
// 範囲がソート済みか判定します。(C++11)
std::vector<int> r = { 2, 3, 5, 1, 4 };
bool is_sorted = std::ranges::is_sorted(r);
std::cout << "is_sorted = " << std::boolalpha << is_sorted << std::endl; // is_sorted = false
}
{
// 範囲のソートされていない位置を取得します。(C++11)
std::vector<int> r = { 2, 3, 5, 1, 4 };
auto is_sorted_until = std::ranges::is_sorted_until(r);
output(r, is_sorted_until); // 位置:3 値:1
}
return 0;
}
コメント