404 Not Found

404 Not Found


nginx

STLのアルゴリズム

[第]34[課では]STLコンテナについて学び、[データを格納するために何を使うか]を[理解しました]。

[ただ]コンテナ[だけでは不十分]――[さらに][データの処理]も必要です:[検索]、[並べ替え]、[集計]、[変換]……

[自分で書く場合]、[数十行は書かなければならないかもしれない]が、STLアルゴリズムを使えば、[たった1行で済む]


1. STLアルゴリズム[概要]

(1) 1.1 STLアルゴリズムとは?

STLアルゴリズムとは、C++標準ライブラリが提供する一連の[汎用]関数テンプレートであり、[コンテナ内のデータ]を操作するために用いられる。

[なぜ]STLアルゴリズムを使うのか?

[自作] STLアルゴリズム
[記入]ループ [一行]コード
[ミスが起きやすい] [厳格なテストを経た]
パフォーマンス[必ずしも高いとは限らない] [高度な]最適化
コード[長] コード[簡潔]

[生活]クラス[比]:


(2) 1.2 アルゴリズムヘッダーファイル

[大多数]STLアルゴリズムは、algorithmヘッダーファイル内の[数]valuealgorithm[に] numeric [含まれている]。

▶ サンプル 2: STLアルゴリズム[応用] (難易度 ⭐)

CPP
#include algorithm // ...
#include numeric // (accumulate)
▶ 試してみよう

(3) 1.3 アルゴリズム[分]クラス

STLアルゴリズム[機能別に分類された]クラス:

カテゴリ [代表的な]アルゴリズム [説明]
[変更なし]アルゴリズム findcountfor_each [変更なし]コンテナ[内容]
[編集]アルゴリズム copytransformreplace [編集]コンテナ[内容]
[ソート]アルゴリズム sortstable_sortpartial_sort [ソート関連]
[二分探索] binary_searchlower_bound [ソート済みの区間での検索]
[マージ]アルゴリズム mergeinplace_merge [ソート済み区間のマージ]
[数]valuealgorithm accumulateinner_product [数]value[計算]
[集合]アルゴリズム set_unionset_intersection [集合演算]


2. [変更なし]アルゴリズム

(1) 2.1 検索——[要素の検索]

[機能]: [container]内で指定された要素を検索し、[iterator]を返す。

[原型]:

CPP
InputIt find(InputIt first, InputIt last, const T& value);

例:[成績を検索] (難易度 ⭐)

CPP
#include iostream
#include vector
#include algorithm

int main() {
 std::vectorint scores = {85, 92, 78, 90, 88};
 
 // 90
 auto it = std::find(scores.begin(), scores.end(), 90);
 
 if (it != scores.end()) {
 // ()
 int index = std::distance(scores.begin(), it);
 std::cout << "90,:" << index << std::endl;
 } else {
 std::cout << "90" << std::endl;
 }
 
 return 0;
}

[実行結果]:

TEXT
90,:3

💡 ヒント:


(2) 2.2 カウント——[計数]

[機能]: [指定された]value[に等しい要素の数を]container[内で]集計します。

例:[満点者の人数を統計する] (難易度 ⭐)

CPP
#include iostream
#include vector
#include algorithm

int main() {
 std::vectorint scores = {100, 85, 100, 92, 78, 100};
 
 // points(100points)
 int perfect = std::count(scores.begin(), scores.end(), 100);
 
 std::cout << "points:" << perfect << std::endl; // output:3
 
 return 0;
}

(3) 2.3 for_each——[反復処理]

[機能]: [container]内の各要素に対して指定された操作を実行する。

例:[すべての成績を印刷] (難易度 ⭐)

CPP
#include iostream
#include vector
#include algorithm

int main() {
 std::vectorint scores = {85, 92, 78, 90, 88};
 
 // lambda
 std::for_each(scores.begin(), scores.end(), (int s) {
 std::cout << s << " ";
 });
 std::cout << std::endl;
 
 return 0;
}

[実行結果]:

TEXT
85 92 78 90 88 

💡 ヒント:



3. [修正]アルゴリズム

(1) 3.1 コピー——[コピー]

[機能]: [ある範囲の要素を別の範囲にコピーする]。

例:array[コピー] (難易度 ⭐)

CPP
#include iostream
#include vector
#include algorithm

int main() {
 std::vectorint src = {1, 2, 3, 4, 5};
 std::vectorint dst(5); //,5
 
 // ...
 std::copy(src.begin(), src.end(), dst.begin());
 
 // ...
 for (int x : dst) {
 std::cout << x << " ";
 }
 std::cout << std::endl;
 
 return 0;
}

(2) 3.2 変換——[変換]

[機能]: [ある範囲の要素を変換し、別の範囲にコピーする]。

例:[成績の加重] (難易度 ⭐⭐)

CPP
#include iostream
#include vector
#include algorithm

int main() {
 std::vectorint scores = {85, 92, 78, 90, 88};
 std::vectorint adjusted(scores.size()); // ...
 
 // 70%,30%
 std::transform(scores.begin(), scores.end(), adjusted.begin(),
 (int s) { return s * 0.7 + 90 * 0.3; });
 
 std::cout << ":";
 for (int x : adjusted) {
 std::cout << x << " ";
 }
 std::cout << std::endl;
 
 return 0;
}

[実行結果]:

91.9 81.6 90 88.6

(3) 3.3 置換——[置換]

[機能]: [container]内の[特定の]value[に等しい要素を、別の]value[に置き換える]。

例:[追試験の成績処理] (難易度 ⭐)

CPP
#include iostream
#include vector
#include algorithm

int main() {
 std::vectorint scores = {85, 92, 78, 90, 88};
 
 // (<60)60()
 std::replace_if(scores.begin(), scores.end(),
 (int s) { return s < 60; },
 60);
 
 std::cout << ":";
 for (int x : scores) {
 std::cout << x << " ";
 }
 std::cout << std::endl;
 
 return 0;
}


4. [ソート]アルゴリズム

(1) 4.1 ソート——[ソート]

[機能]: [container]の範囲をソート([デフォルトは昇順])。

例:[成績順] (難易度 ⭐)

CPP
#include iostream
#include vector
#include algorithm

int main() {
 std::vectorint scores = {85, 92, 78, 90, 88};
 
 // ...
 std::sort(scores.begin(), scores.end());
 
 std::cout << ":";
 for (int x : scores) {
 std::cout << x << " ";
 }
 std::cout << std::endl;
 
 // ...
 std::sort(scores.begin(), scores.end(), std::greaterint());
 
 std::cout << ":";
 for (int x : scores) {
 std::cout << x << " ";
 }
 std::cout << std::endl;
 
 return 0;
}

[実行結果]:

85 88 90 92:92 90 88 85 78

(2) 4.2 [カスタム並べ替えルール]

例:[成績の高い順に学生を並べ替える] (難易度 ⭐⭐)

CPP
#include iostream
#include vector
#include algorithm
#include string

struct Student {
 std::string name;
 int score;
};

int main() {
 std::vectorStudent students = {
 {"...", 85},
 {"...", 92},
 {"...", 78}
 };
 
 // ...
 std::sort(students.begin(), students.end(),
 (const Student& a, const Student& b) {
 return a.score > b.score;
 });
 
 std::cout << ":" << std::endl;
 for (const auto& s : students) {
 std::cout << s.name << ":" << s.score << std::endl;
 }
 
 return 0;
}

[実行結果]:



5. [数]valuealgorithm

(1) 5.1 累積——[累加]

[機能]: [指定範囲内の要素の累積和を計算する]。

例:[合計点を計算する] (難易度 ⭐)

CPP
#include iostream
#include vector
#include numeric

int main() {
 std::vectorint scores = {85, 92, 78, 90, 88};
 
 // points
 int total = std::accumulate(scores.begin(), scores.end(), 0);
 
 std::cout << "points:" << total << std::endl; // output:433
 std::cout << "points:" << total / 5.0 << std::endl; // output:86.6
 
 return 0;
}

(2) 5.2 [内積]

例:[ベクトルの内積] (難易度 ⭐⭐)

CPP
#include iostream
#include vector
#include numeric

int main() {
 std::vectorint v1 = {1, 2, 3};
 std::vectorint v2 = {4, 5, 6};
 
 //:1*4 + 2*5 + 3*6 = 32
 int dot_product = std::inner_product(v1.begin(), v1.end(), v2.begin(), 0);
 
 std::cout << ":" << dot_product << std::endl; // output:32
 
 return 0;
}


6. [総合]例

▶ サンプル 1: [成績分析システム] (難易度 ⭐⭐⭐)

CPP
#include iostream
#include vector
#include algorithm
#include numeric
#include string

int main() {
 std::vectorint scores = {85, 92, 78, 90, 88, 76, 95, 83, 89, 91};
 
 // 1.
 int count = scores.size();
 std::cout << ":" << count << std::endl;
 
 // 2. and
 int total = std::accumulate(scores.begin(), scores.end(), 0);
 double average = static_castdouble(total) / count;
 std::cout << "points:" << total << ",points:" << average << std::endl;
 
 // 3. searchingand
 int max_score = *std::max_element(scores.begin(), scores.end());
 int min_score = *std::min_element(scores.begin(), scores.end());
 std::cout << "points:" << max_score << ",points:" << min_score << std::endl;
 
 // 4.
 int passed = std::count_if(scores.begin(), scores.end(),
 (int s) { return s >= 60; });
 std::cout << ":" << passed << std::endl;
 
 // 5. sortingandoutput3
 std::vectorint top3 = scores;
 std::sort(top3.begin(), top3.end(), std::greaterint());
 std::cout << "3:";
 for (int i = 0; i < 3; i++) {
 std::cout << top3[i] << " ";
 }
 std::cout << std::endl;
 
 return 0;
}
▶ 試してみよう

[実行結果]:

3:95 92 91 


7. アルゴリズム[活用のコツ]

(1) 7.1 イテレータ[補助]関数

関数 [機能]
std::distance(first, last) [2つの]イテレータ[間の距離を計算する]
std::advance(it, n) [イテレータを]n[ステップ][前進]
std::next(it) [戻る・次へ]iterator
std::prev(it) [前のページに戻る]iterator

(2) 7.2 ラムダ[式の上級編]

Lambda[式は]STLアルゴリズム[の相棒]です:

CPP
// ...
[capture](parameters) -> return_type { body }

//:
std::sort(students.begin(), students.end(),
 (const Student& a, const Student& b) {
 if (a.score != b.score)
 return a.score > b.score; // ...
 return a.name < b.name; // ...
 });

❓ よくある質問

Q STLアルゴリズムとループ、どちらが速い?
A STLアルゴリズムの方が通常は速い。その理由は: - 高度に最適化されている - コンテナごとに特化されたバージョンがある - コンパイラによる最適化がより効果的に行える

Q [すべての]コンテナ[で]STLアルゴリズム[は使える]のか?
A [理論的には可能]だが、[効率は異なる]: - [シーケンシャル]コンテナ(vectordeque):[効率が高い] - [連想]コンテナ(setmap):[独自の]メンバ関数があり、[メンバ関数を使う方が][速い]

Q:ラムダ式とは何ですか? A:ラムダ式とは、C++11で導入された匿名関数であり、関数が必要な場所で直接定義することができます。

[基本構文]:

CPP
[capture](params) -> return_type { body }

例:

CPP
auto add = (int a, int b) { return a + b; };
std::cout << add(3, 5) << std::endl; // output:8

Q アルゴリズム[エラーが出た場合はどうすればいいですか]?
A [よくある]エラー: 1. コンテナ[ソートされていない状態で二分探索を使用] → [先にソートする] 2. [対象]コンテナ[容量不足] → back_inserterを使用する 3. イテレータ型[不一致] → [コンテナ型]を確認する

📖 まとめ

[知識ポイント] [要点]
STLアルゴリズム [汎用]関数テンプレート,[操作]コンテナ[データ]
[変更なし]アルゴリズム findcountfor_each
[編集]アルゴリズム copytransformreplace
[ソート]アルゴリズム sort + [カスタム比較]関数
[数]valuealgorithm accumulate([累加])
ラムダ [匿名]関数,[組み合わせ]アルゴリズム[使用]

[学習のヒント]:


📝 練習問題

  1. **初心者(難易度 ⭐):[vectorint を作成し]、[10個の乱数]を[格納し]、[sort を使って][並べ替えた後]出力し、[reverse を使って][逆順にした後]出力する。

  2. **中級(難易度 ⭐⭐):[用] find [在] vectorstring [中查找指定]string,[用] count [统计某个]value[出现的次数]。

  3. **上級(難易度 ⭐⭐⭐):[用] remove_if [と] lambda [を用いて]「[ベクトル] 内のすべての偶数を削除する」という操作を実装する。[erase-remove の慣用表現]を理解する。



[次のレッスン]: 演習:OOP[総合](#36)—— [オブジェクト指向の考え方を用いて学生管理システムを再構築する]

Web-Tutorial.com

Web-Tutorial 技術チーム

複数の開発者によって共同維持されているプログラミングチュートリアルプラットフォーム。各チュートリアルは専門分野の開発者が執筆・レビューしています。正確で信頼性の高いコンテンツを目指しています — 問題を見つけた場合はお知らせください。

100%