sort関数の基本的な使い方
C++のsort関数は、配列やベクターなどの範囲をソートするために使用されます。この関数は<algorithm>ヘッダーファイルに定義されています。
基本的な使い方は以下の通りです:
#include <algorithm> // sort関数を使用するために必要
#include <vector>    // vectorを使用するために必要
int main() {
    std::vector<int> v = {4, 2, 5, 3, 1};
    std::sort(v.begin(), v.end());
    for(int i : v) {
        std::cout << i << " ";
    }
    return 0;
}
このコードは、ベクターvをソートし、その結果を出力します。出力は1 2 3 4 5となります。
sort関数は、最初の2つの引数としてソートする範囲の始まりと終わりを取ります。これらは通常、コンテナのbegin()とend()メソッドによって提供されます。
sort関数はデフォルトで昇順(小さい順)にソートしますが、第三引数を使用してソートの挙動をカスタマイズすることも可能です。これについては次のセクションで詳しく説明します。
第三引数の役割と使い方
C++のsort関数は、第三引数としてカスタムコンパレータを受け取ることができます。このカスタムコンパレータは、ソートの挙動をカスタマイズするために使用されます。
例えば、降順(大きい順)にソートしたい場合は、次のようにsort関数を使用します:
#include <algorithm> // sort関数を使用するために必要
#include <vector>    // vectorを使用するために必要
int main() {
    std::vector<int> v = {4, 2, 5, 3, 1};
    std::sort(v.begin(), v.end(), std::greater<int>());
    for(int i : v) {
        std::cout << i << " ";
    }
    return 0;
}
このコードは、ベクターvを降順にソートし、その結果を出力します。出力は5 4 3 2 1となります。
ここで、std::greater<int>は、sort関数の第三引数として渡されるカスタムコンパレータです。このコンパレータは、二つの整数を比較し、最初の整数が二つ目の整数よりも大きい場合にtrueを返します。これにより、sort関数は降順にソートを行います。
このように、sort関数の第三引数を使用することで、ソートの挙動を自由にカスタマイズすることが可能です。次のセクションでは、カスタムコンパレータの作成と利用について詳しく説明します。
カスタムコンパレータの利用
C++のsort関数の第三引数として、自分で定義したカスタムコンパレータを使用することができます。カスタムコンパレータは、二つの要素を比較し、一つ目の要素が二つ目の要素よりも”小さい”場合にtrueを返す関数です。
以下に、カスタムコンパレータを使用して、ベクターの要素を絶対値の昇順にソートする例を示します:
#include <algorithm> // sort関数を使用するために必要
#include <vector>    // vectorを使用するために必要
#include <cmath>     // abs関数を使用するために必要
// カスタムコンパレータ
bool compareAbs(int a, int b) {
    return std::abs(a) < std::abs(b);
}
int main() {
    std::vector<int> v = {4, -2, -5, 3, 1};
    std::sort(v.begin(), v.end(), compareAbs);
    for(int i : v) {
        std::cout << i << " ";
    }
    return 0;
}
このコードは、ベクターvの要素を絶対値の昇順にソートし、その結果を出力します。出力は1 -2 3 4 -5となります。
ここで、compareAbsは、二つの整数の絶対値を比較し、一つ目の整数の絶対値が二つ目の整数の絶対値よりも小さい場合にtrueを返すカスタムコンパレータです。これにより、sort関数は絶対値の昇順にソートを行います。
このように、カスタムコンパレータを使用することで、sort関数の挙動を自由にカスタマイズすることが可能です。次のセクションでは、演算子<と比較関数/ファンクタの違いについて詳しく説明します。
演算子<と比較関数/ファンクタの違い
C++のsort関数は、デフォルトで<演算子を使用して要素を比較します。しかし、第三引数として比較関数やファンクタ(関数オブジェクト)を指定することで、ソートの挙動をカスタマイズすることができます。
演算子<
<演算子は、二つの要素を比較し、一つ目の要素が二つ目の要素よりも小さい場合にtrueを返します。これは、sort関数のデフォルトの比較方法です。
std::vector<int> v = {4, 2, 5, 3, 1};
std::sort(v.begin(), v.end()); // 昇順にソート
比較関数
比較関数は、二つの要素を比較し、一つ目の要素が二つ目の要素よりも”小さい”場合にtrueを返す関数です。比較関数を使用すると、sort関数の挙動を自由にカスタマイズすることが可能です。
bool compare(int a, int b) {
    return a > b; // 降順にソート
}
std::vector<int> v = {4, 2, 5, 3, 1};
std::sort(v.begin(), v.end(), compare);
ファンクタ(関数オブジェクト)
ファンクタは、関数のように振る舞うオブジェクトです。ファンクタを使用すると、比較関数と同様にsort関数の挙動を自由にカスタマイズすることが可能です。また、ファンクタは状態を持つことができるため、比較関数よりも柔軟な挙動を実現することが可能です。
struct Compare {
    bool operator()(int a, int b) {
        return a > b; // 降順にソート
    }
};
std::vector<int> v = {4, 2, 5, 3, 1};
std::sort(v.begin(), v.end(), Compare());
以上のように、sort関数は<演算子、比較関数、ファンクタのいずれを使用しても要素を比較することができます。これらの違いを理解することで、sort関数をより効果的に使用することが可能です。次のセクションでは、実例による理解について詳しく説明します。
実例による理解
ここでは、C++のsort関数とカスタムコンパレータを使用した具体的な例を通じて、その理解を深めていきます。
例1:ペアの第二要素でソート
ペアのベクターをペアの第二要素でソートする例を考えてみましょう。
#include <algorithm> // sort関数を使用するために必要
#include <vector>    // vectorを使用するために必要
// カスタムコンパレータ
bool comparePair(const std::pair<int, int>& a, const std::pair<int, int>& b) {
    return a.second < b.second;
}
int main() {
    std::vector<std::pair<int, int>> v = {{1, 4}, {2, 3}, {3, 2}, {4, 1}};
    std::sort(v.begin(), v.end(), comparePair);
    for(const auto& p : v) {
        std::cout << "(" << p.first << ", " << p.second << ") ";
    }
    return 0;
}
このコードは、ペアのベクターvをペアの第二要素で昇順にソートし、その結果を出力します。出力は(4, 1) (3, 2) (2, 3) (1, 4)となります。
例2:文字列の長さでソート
文字列のベクターを文字列の長さでソートする例を考えてみましょう。
#include <algorithm> // sort関数を使用するために必要
#include <vector>    // vectorを使用するために必要
#include <string>    // stringを使用するために必要
// カスタムコンパレータ
bool compareLength(const std::string& a, const std::string& b) {
    return a.length() < b.length();
}
int main() {
    std::vector<std::string> v = {"apple", "banana", "cherry", "date"};
    std::sort(v.begin(), v.end(), compareLength);
    for(const auto& s : v) {
        std::cout << s << " ";
    }
    return 0;
}
このコードは、文字列のベクターvを文字列の長さで昇順にソートし、その結果を出力します。出力はdate apple cherry bananaとなります。
以上のように、sort関数とカスタムコンパレータを使用することで、様々な条件でのソートを実現することが可能です。これらの実例を通じて、sort関数の使い方とその柔軟性を理解することができました。