JP / EN

広告
2025/02/16

C++でstd::vectorなどから最小/最大の要素を求めるstd::minmax_element

タグ:c++

C++でstd::vectorなどのコンテナに格納された値のうちの最大値や最小値を求めたいことがままある。 モダンな言語だとminやmaxのような関数がリストなどのデータ型にも直接適用でき足りするのだが、 C++ではあいにくstd::max, std::minは2つの値の比較専用である。
std::vectorに代表されるコンテナ型から最大値や最小値を求めるためにmin_element, max_element, そして両方を求めるminmax_elementが別に用意されている。
algorithmヘッダをインクルードして使ってみよう。

例えばvectorから最小の要素を求めるには、もっとも単純には次のようにstd::min_elementを C++のコンテナに対するアルゴリズムにはよくあるように、始点と終点を渡せばよい。
    #include<algorithm>
    #include<vector>
    #include<iostream>
    
    int main()
    {
      std::vector<<int> v = {1, 2, 3, 4, 5};
      auto minimum = std::min_element(std::begin(v), std::end(v));
      std::cout << *minimum << std::endl;
      // 実行すると1が出力される
      return 0;
    }
  
返り値は引数として与えられたコンテナに対するイテレータ型になる。 イテレータはポインタのように扱えばよく、値を取り出すには*演算子を適用する必要があることに注意。
最大値は同様にstd::max_elementを使えばよい。

最小値と最大値の両方が欲しいときは、 別々に呼びだしてもよいのだが、vector全体に対するforループを2つ分回すことになり特にvectorが大きいといはもったいない。 一度のループで両方を求めてくれる:
    #include<algorithm>
    #include<vector>
    #include<iostream>

    int main()
    {
      std::vector<int> v = {1, 2, 3, 4, 5};
      auto min_max = std::minmax_element(std::begin(v), std::end(v));
      std::cout << *min_max.first << std::endl;
      std::cout << *min_max.second << std::endl;
      return 0;
    }
  
この場合返り値はイテレータをふたつ格納したstd::pairとなる。 *min_max.firstで最小値、>*min_max.secondで最大値が取り出せる。

さらに発展的な使い方として、比較方法を関数オブジェクトやラムダ式として渡して指定することもできる。 要素の型本来の比較演算子として定義されている以外の方法での比較により最大値・最小値を求めることもでき、 便利である。
例えば文字列型を「文字列長さが小さいほうが小さい」というルールに基づいて比較することにすれば、 最短の長さの文字列をみつけるという使い方ができる:
    #include<algorithm>
    #include<vector>
    #include<iostream>
    
    int main()
    {
      std::vector<std::string> v = {"aaa", "bb", "c"};
      auto minimum = std::min_element(std::begin(v), std::end(v),
        [](auto a, auto b){return a.size() < b.size();});
      std::cout << *minimum << std::endl;
      // 実行するとcが出力される
    }
  
第3引数[](auto a, auto b){return a.size() < b.size();}が比較方法を指定するラムダ式で、 ここに「trueのときにaのほうが小さく、falseのときにaとbが等しいかbの方が小さい」を意味するように関数を 入れておけばよい。比較の向きを間違えないように注意。

おすすめ記事

C++で配列をstd::vectorに、またstd::vectorを配列に変換

C++ STLで0から1の実数値乱数を生成する

std::vector<bool>はテンプレート特殊化して別物になっている



このエントリーをはてなブックマークに追加

https://wonderhorn.net/