STLアルゴリズム

sort, find, transform など.

sort(ソート)

効率的なソートアルゴリズム。カスタム比較関数も指定可能。

#include <iostream>
#include <vector>
#include <algorithm>

int main() {
    std::vector<int> v = {5, 2, 8, 1, 9};
    
    // 昇順
    std::sort(v.begin(), v.end());
    std::cout << "昇順: ";
    for (int x : v) std::cout << x << " ";
    std::cout << std::endl;
    
    // 降順(ラムダ関数で比較)
    std::sort(v.begin(), v.end(), [](int a, int b) { return a > b; });
    std::cout << "降順: ";
    for (int x : v) std::cout << x << " ";
    std::cout << std::endl;
    
    return 0;
}

昇順: 1 2 5 8 9
降順: 9 8 5 2 1

find と find_if(検索)

条件に合致する最初の要素を検索。

#include <iostream>
#include <vector>
#include <algorithm>

int main() {
    std::vector<int> v = {1, 2, 3, 4, 5};
    
    // 値で検索
    auto it1 = std::find(v.begin(), v.end(), 3);
    if (it1 != v.end()) {
        std::cout << "find: " << *it1 << " が見つかりました" << std::endl;
    }
    
    // 条件で検索
    auto it2 = std::find_if(v.begin(), v.end(), 
                            [](int x) { return x > 3; });
    if (it2 != v.end()) {
        std::cout << "find_if: " << *it2 << " (>3) が見つかりました" << std::endl;
    }
    
    return 0;
}

find: 3 が見つかりました
find_if: 4 (>3) が見つかりました

transform(変換)

コンテナの各要素を変換して別のコンテナに格納。

#include <iostream>
#include <vector>
#include <algorithm>

int main() {
    std::vector<int> v = {1, 2, 3, 4, 5};
    std::vector<int> result;
    
    // 二乗
    std::transform(v.begin(), v.end(), std::back_inserter(result),
                   [](int x) { return x * x; });
    
    std::cout << "二乗結果: ";
    for (int x : result) std::cout << x << " ";
    std::cout << std::endl;
    
    return 0;
}

二乗結果: 1 4 9 16 25

count と count_if(カウント)

条件を満たす要素の個数を数える。

#include <iostream>
#include <vector>
#include <algorithm>

int main() {
    std::vector<int> scores = {85, 92, 78, 92, 88, 92};
    
    // 値でカウント
    int count92 = std::count(scores.begin(), scores.end(), 92);
    std::cout << "92の個数: " << count92 << std::endl;
    
    // 条件でカウント
    int highScores = std::count_if(scores.begin(), scores.end(),
                                   [](int s) { return s >= 90; });
    std::cout << "90以上のスコア: " << highScores << std::endl;
    
    return 0;
}

92の個数: 3
90以上のスコア: 2

copy と copy_if(コピー)

要素を別のコンテナにコピー。条件付きコピーも可能。

#include <iostream>
#include <vector>
#include <algorithm>

int main() {
    std::vector<int> src = {1, 2, 3, 4, 5, 6, 7, 8};
    std::vector<int> dest1, dest2;
    
    // すべてコピー
    std::copy(src.begin(), src.end(), std::back_inserter(dest1));
    
    // 偶数のみコピー
    std::copy_if(src.begin(), src.end(), std::back_inserter(dest2),
                 [](int x) { return x % 2 == 0; });
    
    std::cout << "全コピー: ";
    for (int x : dest1) std::cout << x << " ";
    std::cout << std::endl;
    
    std::cout << "偶数のみ: ";
    for (int x : dest2) std::cout << x << " ";
    std::cout << std::endl;
    
    return 0;
}

全コピー: 1 2 3 4 5 6 7 8
偶数のみ: 2 4 6 8

for_each(走査)

各要素に対して関数を実行。

#include <iostream>
#include <vector>
#include <algorithm>

int main() {
    std::vector<std::string> names = {"Alice", "Bob", "Charlie"};
    
    std::cout << "一覧: " << std::endl;
    std::for_each(names.begin(), names.end(),
                  [](const std::string& name) {
                      std::cout << "  - " << name << std::endl;
                  });
    
    return 0;
}

一覧:
- Alice
- Bob
- Charlie

lower_bound と upper_bound(範囲検索)

ソート済みコンテナで特定値以上/より大きい最初の位置を速く検索。

#include <iostream>
#include <vector>
#include <algorithm>

int main() {
    std::vector<int> v = {1, 2, 2, 2, 3, 4, 5};  // ソート済み
    
    // 2以上の最初の位置
    auto lower = std::lower_bound(v.begin(), v.end(), 2);
    std::cout << "lower_bound(2): インデックス " 
              << (lower - v.begin()) << std::endl;
    
    // 2より大きい最初の位置
    auto upper = std::upper_bound(v.begin(), v.end(), 2);
    std::cout << "upper_bound(2): インデックス "
              << (upper - v.begin()) << std::endl;
    
    return 0;
}

lower_bound(2): インデックス 1
upper_bound(2): インデックス 4

よくある誤り

  • 誤り: ソートされていないコンテナで lower_bound を使用 → 改善: 必ず事前に sort() する
  • 誤り: std::find に O(1) を期待 → 改善: 通常は O(N)、hashで O(1)が必要なら unordered_set を使う
  • 誤り: back_inserter なしで transform → 改善: std::back_inserter(result) で新規要素追加
  • 誤り: find() で見つからない場合の処理忘れ → 改善: it != container.end() の確認

ポイント

  • std::sort: O(N log N) の効率的なソート
  • std::find/find_if: 線形探索で条件判定可能
  • std::transform: 関数またはラムダで変換
  • ラムダ関数でカスタムロジックを定義できる
  • lower_bound/upper_bound は事前ソート必須