خوارزميات STL
جزء من قسم Object Oriented Programming في رحلة C++ على Coddy — الدرس 73 من 104.
تُعد خوارزميات STL دوال قالبية (template functions) تعمل على نطاقات محددة بواسطة المكررات (iterators). وهي موجودة في الترويسات <algorithm> و <numeric> وتعمل مع أي حاوية (container) توفر مكررات متوافقة.
std::sort يرتب العناصر بترتيب تصاعدي افتراضيًا:
#include <algorithm>
#include <vector>
std::vector<int> nums = {5, 2, 8, 1};
std::sort(nums.begin(), nums.end());
// nums: {1, 2, 5, 8}std::find يبحث عن قيمة ويعيد مكرراً (iterator) لأول تطابق، أو end() إذا لم يتم العثور عليها:
auto it = std::find(nums.begin(), nums.end(), 5);
if (it != nums.end()) {
std::cout << "Found at index: " << (it - nums.begin());
}std::transform يقوم بتطبيق عملية على كل عنصر ويخزن النتائج في نطاق الوجهة:
std::vector<int> doubled(nums.size());
std::transform(nums.begin(), nums.end(), doubled.begin(),
[](int x) { return x * 2; });
// doubled: {2, 4, 10, 16}std::accumulate من <numeric> يجمع كافة العناصر في قيمة واحدة:
#include <numeric>
int sum = std::accumulate(nums.begin(), nums.end(), 0);
// sum: 16 (1 + 2 + 5 + 8)تقبل هذه الخوارزميات نطاقات المكررات (iterator ranges) بدلاً من الحاويات مباشرةً، مما يجعلها مرنة بما يكفي للعمل على نطاقات جزئية أو أنواع حاويات مختلفة باستخدام نفس الكود.
التحدي
سهللنقم ببناء محلل درجات (score analyzer) يعالج مجموعة من الأرقام باستخدام خوارزميات STL. ستقوم بإنشاء دوال مساعدة توضح كيفية عمل sort و find و transform و accumulate معاً لتحليل البيانات.
ستقوم بتنظيم الكود الخاص بك عبر ملفين:
ScoreAnalyzer.h: قم بتعريف دوال مساعدة تستخدم خوارزميات STL لمعالجة متجهات (vectors) من الأعداد الصحيحة.أنشئ دالة تسمى
sortScoresتأخذstd::vector<int>&وتقوم بفرزها بترتيب تصاعدي باستخدامstd::sort.أنشئ دالة تسمى
findScoreتأخذconst std::vector<int>&وقيمة مستهدفة من نوعint. استخدمstd::findللبحث عن القيمة المستهدفة. إذا تم العثور عليها، فقم بإرجاع الفهرس (المسافة من البداية). إذا لم يتم العثور عليها، فقم بإرجاع-1.أنشئ دالة تسمى
applyBonusتأخذconst std::vector<int>&ومبلغ مكافأة (bonus) من نوعint. استخدمstd::transformلإنشاء وإرجاع متجه جديد حيث يتم إضافة المكافأة إلى كل درجة.أنشئ دالة تسمى
calculateAverageتأخذconst std::vector<int>&وترجع المتوسط كـdouble. استخدمstd::accumulateلحساب المجموع، ثم اقسمه على الحجم.أنشئ دالة تسمى
printVectorتأخذconst std::vector<int>&وتطبع جميع العناصر مفصولة بمسافات، متبوعة بسطر جديد.main.cpp: اقرأ ستة مدخلات (كل منها في سطر منفصل):- الدرجة الأولى (عدد صحيح)
- الدرجة الثانية (عدد صحيح)
- الدرجة الثالثة (عدد صحيح)
- الدرجة الرابعة (عدد صحيح)
- درجة للبحث عنها (عدد صحيح)
- مبلغ مكافأة لتطبيقه (عدد صحيح)
أنشئ متجهاً بالدرجات الأربع واستعرض الخوارزميات:
- اطبع
Original:متبوعاً بمحتويات المتجه - قم بفرز الدرجات واطبع
Sorted:متبوعاً بالمتجه المفرز - ابحث عن الدرجة المستهدفة في المتجه المفرز. إذا تم العثور عليها، اطبع
Found <value> at index <index>. إذا لم يتم العثور عليها، اطبع<value> not found - طبق المكافأة على الدرجات المفرزة واطبع
With bonus:متبوعاً بالمتجه الجديد - احسب واطبع متوسط الدرجات المفرزة الأصلية (قبل المكافأة) كـ
Average: <value>مع منزلة عشرية واحدة
على سبيل المثال، مع المدخلات 75، 90، 60، 85، 85، و 5:
Original: 75 90 60 85
Sorted: 60 75 85 90
Found 85 at index 2
With bonus: 65 80 90 95
Average: 77.5مع المدخلات 100، 80، 95، 70، 50، و 10:
Original: 100 80 95 70
Sorted: 70 80 95 100
50 not found
With bonus: 80 90 105 110
Average: 86.2تذكر تضمين <algorithm> من أجل sort و find و transform، و <numeric> من أجل accumulate. استخدم std::fixed و std::setprecision(1) من <iomanip> لتنسيق المتوسط.
ورقة مرجعية
خوارزميات STL هي دوال قالب (template functions) من <algorithm> و <numeric> تعمل على نطاقات محددة بواسطة المكررات (iterators).
تقوم std::sort بترتيب العناصر بترتيب تصاعدي:
#include <algorithm>
#include <vector>
std::vector<int> nums = {5, 2, 8, 1};
std::sort(nums.begin(), nums.end());
// nums: {1, 2, 5, 8}تبحث std::find عن قيمة وتُرجع مكررًا (iterator) لأول تطابق، أو end() إذا لم يتم العثور عليها:
auto it = std::find(nums.begin(), nums.end(), 5);
if (it != nums.end()) {
std::cout << "Found at index: " << (it - nums.begin());
}تقوم std::transform بتطبيق عملية على كل عنصر وتخزين النتائج في نطاق وجهة (destination range):
std::vector<int> doubled(nums.size());
std::transform(nums.begin(), nums.end(), doubled.begin(),
[](int x) { return x * 2; });
// doubled: {2, 4, 10, 16}تقوم std::accumulate من <numeric> بدمج جميع العناصر في قيمة واحدة:
#include <numeric>
int sum = std::accumulate(nums.begin(), nums.end(), 0);
// sum: 16 (1 + 2 + 5 + 8)تعمل هذه الخوارزميات مع نطاقات المكررات (iterator ranges)، مما يجعلها مرنة للنطاقات الجزئية أو أنواع الحاويات المختلفة.
جرّب بنفسك
#include <iostream>
#include <vector>
#include <iomanip>
#include "ScoreAnalyzer.h"
using namespace std;
int main() {
// قراءة ستة مدخلات
int score1, score2, score3, score4;
int searchTarget, bonusAmount;
cin >> score1;
cin >> score2;
cin >> score3;
cin >> score4;
cin >> searchTarget;
cin >> bonusAmount;
// TODO: إنشاء vector يحتوي على الدرجات الأربع
// TODO: طباعة "Original:" متبوعة بمحتويات الـ vector
// TODO: فرز الدرجات وطباعة "Sorted:" متبوعة بالـ vector المفرز
// TODO: البحث عن الدرجة المستهدفة في الـ vector المفرز
// إذا تم العثور عليها، اطبع "Found <value> at index <index>"
// إذا لم يتم العثور عليها، اطبع "<value> not found"
// TODO: تطبيق المكافأة (bonus) على الدرجات المفرزة وطباعة "With bonus:" متبوعة بالـ vector الجديد
// TODO: حساب وطباعة متوسط الدرجات المفرزة (قبل المكافأة)
// استخدم fixed و setprecision(1) للتنسيق
// اطبعها كـ "Average: <value>"
return 0;
}
يتضمن هذا الدرس اختبارًا قصيرًا. ابدأ الدرس للإجابة عليه وتتبّع تقدمك.
جميع دروس Object Oriented Programming
1أساسيات الـ OOP
الملفات الخارجيةبناء وتجميع (Compilation) لغة C++ملفات الـ Header وملفات الـ Sourceالـ Namespaces والـ Scopeمقدمة في الـ OOP في C++الـ Classes مقابل الـ Objectsالمؤشر 'this'الـ Methods (الدوال الأعضاء)الـ Attributes (بيانات الأعضاء)أساسيات الـ Ctors والـ Dtorsمراجعة - آلة حاسبة بسيطة4خصائص الـ Class
أعضاء الـ Instance مقابل الـ Staticدوال الـ Getters والـ Settersدوال الأعضاء الثابتة (Const)الكلمة المفتاحية Mutableالدوال والمتغيرات الساكنة (Static)الدوال والفئات الصديقة (Friend)مراجعة - مدير الحساب البنكي7الوراثة
الوراثة الأساسيةمستويات الوصول في الوراثةترتيب استدعاء الـ Ctor والـ Dtorإعادة تعريف الدوال (Method Overriding)الدوال الافتراضية والـ VTableالوراثة المتعددةالوراثة الافتراضيةمراجعة - هيكلية الموظفين10نظرة عامة على STL
نظرة عامة وفلسفة STLحاويات STLالـ Iteratorsخوارزميات STLالـ Functors وتعبيرات Lambdaمراجعة - تكرار الكلمات13أنماط التصميم - الجزء الأول
مقدمة في أنماط التصميمنمط Singletonنمط Factory و Abstract Factoryنمط Builderنمط Observerنمط Strategy2إدارة الذاكرة
ذاكرة Stack مقابل Heapالمؤشرات والمراجعالذاكرة الديناميكية (new/delete)المؤشرات الذكية في C++RAII في C++مراجعة - مدير المصفوفات الديناميكية5التغليف (Encapsulation)
محددات الوصول في C++محددات الوصول بشكل متعمقإخفاء المعلوماتStruct مقابل Classالأصناف المتداخلة والداخليةمراجعة - نظام سجلات الطلاب8تعدد الأشكال (Polymorphism)
تعدد الأشكال: وقت التجميع مقابل وقت التشغيلالتحميل الزائد للدوال (Function Overloading)مراجعة الدوال الافتراضية (Virtual Functions)الدوال الافتراضية البحتة (Pure Virtual Functions)الأصناف المجردة (Abstract Classes)تصميم الواجهات (Interface) في C++التحويل الديناميكي (Dynamic Casting) و RTTIملخص - حاسبة الأشكال11مفاهيم OOP المتقدمة
التركيب مقابل الوراثةالـ Mixins عبر CRTPنمط Pimplمحو النوع (Type Erasure)أصناف Enum والأنواع القويةمعالجة الاستثناءات في OOPتسلسلات الاستثناءات المخصصة14أنماط التصميم - الجزء الثاني
نمط الأمرنمط المحولنمط المزيننمط قالب الطريقةنمط الحالةنمط التركيبRAII كنمط3المنشئات والموادم
المنشئ الافتراضيالمنشئ ذو المعاملاتمنشئ النسخمنشئ النقلقوائم تهيئة المنشئالمنشئات المفوضةتعمق في الموادمقاعدة الثلاثة / الخمسة / الصفرمراجعة - فئة String6تحميل العوامل (Operator Overloading)
مقدمة في تحميل العواملتحميل العوامل الحسابيةتحميل عوامل المقارنةعوامل Streamتحميل عامل التعيينتحميل العوامل [] و ()عوامل تحويل النوعمراجعة - Matrix Class9القوالب
قوالب الدوالقوالب الأصنافتخصيص القوالبالقوالب المتغيرةأساسيات SFINAE و Type Traitsمراجعة - الحاويات العامة