STL Algorithms — C++ المتقدم
خوارزميات STL
بدلاً من كتابة حلقة لكل مهمة، توفر <algorithm> و <numeric> أكثر من 100 خوارزمية مختبرة ومسمّاة. الكود يصبح يصف ماذا تريد:
vector<int> v = {40, 85, 62, 97};
// حلقة يدوية: عليك قراءتها لتفهم أنها تعدّ
int c = 0; for (int x : v) if (x > 50) c++;
// خوارزمية: الاسم يقول كل شيء
auto c2 = count_if(v.begin(), v.end(), [](int x) { return x > 50; });الفكرة: نطاق [begin, end)
كل خوارزمية تعمل على نطاق من مكرِّرين: الأول مشمول والثاني غير مشمول. لذلك تعمل مع vector و deque و array و list وحتى المصفوفات العادية.
أهم الخوارزميات
| المهمة | الخوارزمية |
|---|---|
| بحث عن قيمة / شرط | find / find_if |
| هل يوجد/الكل/لا أحد | any_of / all_of / none_of |
| عدّ | count / count_if |
| ترتيب | sort، stable_sort، partial_sort |
| بحث ثنائي (في مرتّب) | binary_search، lower_bound |
| أكبر/أصغر | max_element، min_element، minmax_element |
| تحويل | transform |
| جمع/طي | accumulate (في <numeric>) |
| عكس / إزالة المكرر المتجاور | reverse / unique |
#include <algorithm>
#include <iostream>
#include <numeric>
#include <vector>
using namespace std;
int main() {
vector<int> v = {40, 85, 62, 97, 55, 30};
sort(v.begin(), v.end()); // 30 40 55 62 85 97
bool anyFail = any_of(v.begin(), v.end(), [](int x) { return x < 50; });
int total = accumulate(v.begin(), v.end(), 0); // ابدأ بـ 0 (int)
auto it = find_if(v.begin(), v.end(), [](int x) { return x > 60; });
vector<int> curved(v.size());
transform(v.begin(), v.end(), curved.begin(), [](int x) { return min(x + 5, 100); });
cout << boolalpha << anyFail << ' ' << total << ' ' << *it << ' ' << curved.back() << '\n';
// true 369 62 100
}⚠️ accumulate(v.begin(), v.end(), 0) مع أعداد عشرية يعطي ناتجاً صحيحاً مقطوعاً لأن النوع يُؤخذ من القيمة الابتدائية. استخدم 0.0.
الحذف: erase-remove
remove_if لا تحذف فعلاً؛ تنقل العناصر المحتفظ بها للأمام وتعيد مكرِّراً لبداية "البقايا". الحذف الحقيقي بـ erase:
#include <algorithm>
#include <vector>
using namespace std;
vector<int> nums = {1, 2, 3, 4, 5, 6};
// الطريقة الكلاسيكية:
// nums.erase(remove_if(nums.begin(), nums.end(), [](int x){ return x % 2 == 0; }), nums.end());
// C++20 — أبسط بكثير:
auto removed = erase_if(nums, [](int x) { return x % 2 == 0; }); // nums = {1, 3, 5}الترتيب بمعيار مخصص
#include <algorithm>
#include <string>
#include <vector>
using namespace std;
struct Student { string name; int score; };
vector<Student> st = {{"سارة", 91}, {"عمر", 78}, {"ليلى", 91}};
// الأعلى درجة أولاً، وعند التساوي أبجدياً
// sort(st.begin(), st.end(), [](const Student& a, const Student& b) {
// return a.score != b.score ? a.score > b.score : a.name < b.name;
// });المقارنة يجب أن تكون "أصغر تماماً" (strict): استخدام >= بدل > يكسر sort (سلوك غير معرّف).
C++20 Ranges
نسخ أبسط تأخذ الحاوية مباشرة، وتدعم التركيب بـ |:
#include <algorithm>
#include <iostream>
#include <ranges>
#include <vector>
using namespace std;
int main() {
vector<int> v = {5, 3, 8, 1, 9, 2};
ranges::sort(v); // بدون begin/end
for (int x : v | views::filter([](int x) { return x % 2 == 1; })
| views::transform([](int x) { return x * x; }))
cout << x << ' '; // 1 9 25 81
cout << '\n';
}الـ views كسولة: لا تنشئ vector وسيطاً، بل تحسب كل عنصر عند الطلب.
تمرين
لديك vector<int> لدرجات: احذف الدرجات غير الصالحة (خارج 0–100) بـ erase_if، ثم احسب المتوسط بـ accumulate و نسبة الناجحين (≥ 50) بـ count_if، واطبع أعلى 3 درجات بـ partial_sort.
#include <iostream>
#include <vector>
#include <algorithm>
#include <numeric>
using namespace std;
int main() {
vector<int> nums = {5, 2, 8, 1, 9, 3, 7, 4, 6};
// ===== Non-modifying =====
cout << "=== Non-modifying ===" << endl;
// find
auto it = find(nums.begin(), nums.end(), 8);
if (it != nums.end()) {
cout << "وجدنا 8 في الموقع: " << (it - nums.begin()) << endl;
}
// count
vector<int> data = {1, 2, 2, 3, 2, 4, 2};
cout << "عدد مرات 2: " << count(data.begin(), data.end(), 2) << endl;
// all_of, any_of, none_of
bool allPositive = all_of(nums.begin(), nums.end(), [](int x) { return x > 0; });
bool hasEven = any_of(nums.begin(), nums.end(), [](int x) { return x % 2 == 0; });
bool noNegative = none_of(nums.begin(), nums.end(), [](int x) { return x < 0; });
cout << "كلها موجبة: " << (allPositive ? "نعم" : "لا") << endl;
cout << "يوجد زوجي: " << (hasEven ? "نعم" : "لا") << endl;
// ===== Modifying =====
cout << "\n=== Modifying ===" << endl;
// transform
vector<int> squared(nums.size());
transform(nums.begin(), nums.end(), squared.begin(),
[](int x) { return x * x; });
cout << "مربعات: ";
for (int n : squared) cout << n << " ";
cout << endl;
// replace
vector<int> replaced = nums;
replace(replaced.begin(), replaced.end(), 5, 50);
cout << "بعد استبدال 5 بـ 50: ";
for (int n : replaced) cout << n << " ";
cout << endl;
// fill
vector<int> filled(5);
fill(filled.begin(), filled.end(), 7);
cout << "ملء بـ 7: ";
for (int n : filled) cout << n << " ";
cout << endl;
// ===== Sorting =====
cout << "\n=== Sorting ===" << endl;
vector<int> toSort = nums;
sort(toSort.begin(), toSort.end());
cout << "تصاعدي: ";
for (int n : toSort) cout << n << " ";
cout << endl;
sort(toSort.begin(), toSort.end(), greater<int>());
cout << "تنازلي: ";
for (int n : toSort) cout << n << " ";
cout << endl;
// partial_sort (أصغر 3)
vector<int> partial = nums;
partial_sort(partial.begin(), partial.begin() + 3, partial.end());
cout << "أصغر 3: ";
for (int i = 0; i < 3; i++) cout << partial[i] << " ";
cout << endl;
// ===== Numeric =====
cout << "\n=== Numeric ===" << endl;
int sum = accumulate(nums.begin(), nums.end(), 0);
cout << "المجموع: " << sum << endl;
int product = accumulate(nums.begin(), nums.end(), 1, multiplies<int>());
cout << "الضرب: " << product << endl;
// ===== Lambda المتقدمة =====
cout << "\n=== Lambda ===" << endl;
// Lambda مع capture
int threshold = 5;
int countAbove = count_if(nums.begin(), nums.end(),
[threshold](int x) { return x > threshold; });
cout << "أكبر من " << threshold << ": " << countAbove << endl;
// Lambda مع modify
vector<int> modified = nums;
int multiplier = 2;
for_each(modified.begin(), modified.end(),
[multiplier](int& x) { x *= multiplier; });
cout << "مضروب في 2: ";
for (int n : modified) cout << n << " ";
cout << endl;
return 0;
}اختبر فهمك