Arc's blog

競プロなど

C++で構造体やクラスをソートする方法まとめ

(Qiitaを退会したため,同名の記事をQiitaからはてなにコピーしました)

C++でクラスや構造体の入ったvectorコンテナをソートする時、「何と何を比較してソートするのか?」を定義しないといけない。幾つか方法があったので自分なりにまとめてみる。

その1 演算子オーバーロード

ソースコード

#include <iostream>
#include <vector>
using std::cin;
using std::cout;
using std::endl;

struct Info
{
    std::string name;
    int age;

    Info(std::string inputted_name, int inputted_age)
    {
        name = inputted_name;
        age = inputted_age;
    }
    bool operator<(const Info &another) const
    {
        return age < another.age;//年齢を比較
    };
    //2つのconstを付けないとコンパイルエラーになるので注意!!
};

int main(void)
{
    std::vector<Info> info;
    info.push_back(Info("foo", 17));
    info.push_back(Info("bar", 80));
    info.push_back(Info("baz", 30));

    std::sort(info.begin(), info.end());//ソート実行

    for (auto itr : info)
    {
        cout << "age:" << itr.age << " name:" << itr.name << endl;
    }

    return 0;
}

出力

age:17 name:foo
age:30 name:baz
age:80 name:bar

解説

operator<を定義しておく方法。sortする時に(暗黙的に)呼ばれたstd::lessoperator<を利用して比較を実行する、と理解している。

operator>を定義しておけば降順ソート(std::greaterを使う方法)もできる。

その2 比較関数を定義する

ソースコード

struct Info
{
    std::string name;
    int age;

    Info(std::string inputted_name, int inputted_age)
    {
        name = inputted_name;
        age = inputted_age;
    }
};

bool cmp(const Info &a, const Info &b)
{
    return a.age < b.age;
}

int main(void)
{
    std::vector<Info> info;
    info.push_back(Info("foo", 17));
    info.push_back(Info("bar", 80));
    info.push_back(Info("baz", 30));

    std::sort(info.begin(), info.end(),cmp);//比較関数cmpを使用してsort

    for (auto itr : info)
    {
        cout << "age:" << itr.age << " name:" << itr.name << endl;
    }

    return 0;
}

出力

age:17 name:foo
age:30 name:baz
age:80 name:bar

解説

sortする時に利用する関数を自力で作っておく方法。

不等号の向きを逆にすれば降順ソートになる。

その3 ラムダ式を使う

ソースコード

struct Info
{
    std::string name;
    int age;

    Info(std::string inputted_name, int inputted_age)
    {
        name = inputted_name;
        age = inputted_age;
    }
};

bool cmp(const Info &a, const Info &b)
{
    return a.age < b.age;
}

int main(void)
{
    std::vector<Info> info;
    info.push_back(Info("foo", 17));
    info.push_back(Info("bar", 80));
    info.push_back(Info("baz", 30));

    std::sort(info.begin(), info.end(), [](const Info &a, const Info &b) {
        return a.age < b.age;
    });//比較関数をラムダ式で作る

    for (auto itr : info)
    {
        cout << "age:" << itr.age << " name:" << itr.name << endl;
    }

    return 0;
}

出力

age:17 name:foo
age:30 name:baz
age:80 name:bar

解説

比較関数をラムダ式としてsort()の所に記述しただけ。シンプルな関数なのでラムダ式で書いたほうが分かりやすいかも?

その他

std::priority_queue()等にも使える。ダイクストラ法を使うときなどに役に立つかもしれない。