0Pricing
C++ Academy · درس

المقارنات المخصّصة

تحكّم في الترتيب

المقارنات المخصّصة درس مجاني في C++ Academy على CoddyKit. هذا هو الدرس 4 من أصل 4. يمكنك قراءة الدرس كاملاً أدناه مجاناً — ثم تمرن عليه مباشرة في المتصفح باستخدام محرر أكواد مدمج ومدرس ذكاء اصطناعي متاح 24/7. هذا الدرس جزء من مسار التعلم في C++ Academy، وتقدمك يتزامن عبر الويب وتطبيق CoddyKit. تتضمن دورة C++ Academy 4 دروس في المجموع.

لماذا نستخدم المقارنات المخصصة؟

ترتب الحاويات المرتبة افتراضياً باستخدام std::less، أي بترتيب تصاعدي. يتيح لك المقارن المخصص تغيير هذا الترتيب، مثل الترتيب التنازلي أو الترتيب حسب حقل محدد.

#include <iostream>
#include <set>

int main() {
    std::set<int> ascending{3, 1, 2};
    for (int x : ascending) std::cout << x << ' ';
    std::cout << '\n';
    return 0;
}

الترتيب التنازلي باستخدام std::greater

أبسط مقارن مخصص هو الكائن الدالي القياسي std::greater، الذي يرتب العناصر ترتيباً تنازلياً.

#include <iostream>
#include <set>
#include <functional>

int main() {
    std::set<int, std::greater<int>> s{3, 1, 2};
    for (int x : s) std::cout << x << ' ';
    std::cout << '\n';
    return 0;
}

المقارن في map

المقارن هو المعامل الثالث في قالب std::map. وهنا تُرتب المفاتيح من الأكبر إلى الأصغر.

#include <iostream>
#include <map>
#include <functional>

int main() {
    std::map<int, std::string, std::greater<int>> m{
        {1, "one"}, {3, "three"}, {2, "two"}
    };
    for (const auto& [k, v] : m) std::cout << k << ':' << v << ' ';
    std::cout << '\n';
    return 0;
}

كيفية عمل المقارنات

المقارن هو كائن قابل للاستدعاء يستقبل وسيطين ويعيد true إذا كان يجب أن يأتي العنصر الأول قبل الثاني. ويجب أن يحدد ترتيباً ضعيفاً صارماً.

#include <iostream>

struct Less {
    bool operator()(int a, int b) const { return a < b; }
};

int main() {
    Less cmp;
    std::cout << std::boolalpha << cmp(2, 5) << '\n';
    std::cout << cmp(5, 2) << '\n';
    return 0;
}

مقارن مخصص باستخدام struct

عرّف struct خاصاً بك ليكون كائناً دالياً، مع operator()، ثم مرر نوعه باعتباره المقارن.

#include <iostream>
#include <set>

struct ByAbs {
    bool operator()(int a, int b) const {
        return (a < 0 ? -a : a) < (b < 0 ? -b : b);
    }
};

int main() {
    std::set<int, ByAbs> s{-5, 3, -1, 4};
    for (int x : s) std::cout << x << ' ';
    std::cout << '\n';
    return 0;
}

ترتيب السلاسل حسب الطول

يمكن للمقارنات مقارنة أي خاصية. وهنا تُرتب السلاسل حسب الطول، ثم أبجدياً لكسر التعادل.

#include <iostream>
#include <set>
#include <string>

struct ByLen {
    bool operator()(const std::string& a, const std::string& b) const {
        if (a.size() != b.size()) return a.size() < b.size();
        return a < b;
    }
};

int main() {
    std::set<std::string, ByLen> s{"bbb", "a", "cc", "dd"};
    for (const auto& x : s) std::cout << x << ' ';
    std::cout << '\n';
    return 0;
}

أهمية كاسرات التعادل

إذا قال المقارن إن أياً من العنصرين لا يسبق الآخر، فستعاملهما الحاوية على أنهما متساويان. وفي set يعني ذلك إسقاط أحدهما باعتباره مكرراً.

#include <iostream>
#include <set>
#include <string>

struct LenOnly {
    bool operator()(const std::string& a, const std::string& b) const {
        return a.size() < b.size();
    }
};

int main() {
    std::set<std::string, LenOnly> s{"ab", "cd", "x"};
    std::cout << s.size() << " elements\n";
    return 0;
}

استخدام Lambdas كمقارنات

يمكنك استخدام lambda بتمرير نوعها عبر decltype وتمرير lambda نفسها إلى المُنشئ.

#include <iostream>
#include <set>

int main() {
    auto cmp = [](int a, int b) { return a > b; };
    std::set<int, decltype(cmp)> s(cmp);
    s.insert(1);
    s.insert(3);
    s.insert(2);
    for (int x : s) std::cout << x << ' ';
    std::cout << '\n';
    return 0;
}

المقارنات في priority_queue

تُستخدم المقارنات أيضاً لإعداد std::priority_queue. ومع std::greater تصبح كومة صغرى.

#include <iostream>
#include <queue>
#include <vector>
#include <functional>

int main() {
    std::priority_queue<int, std::vector<int>, std::greater<int>> pq;
    pq.push(5); pq.push(1); pq.push(3);
    while (!pq.empty()) { std::cout << pq.top() << ' '; pq.pop(); }
    std::cout << '\n';
    return 0;
}

مقارنة الأزواج

لترتيب مجموعة من الأزواج حسب العنصر الثاني، اكتب مقارناً يفحص .second.

#include <iostream>
#include <set>
#include <utility>

struct BySecond {
    bool operator()(const std::pair<int,int>& a, const std::pair<int,int>& b) const {
        return a.second < b.second;
    }
};

int main() {
    std::set<std::pair<int,int>, BySecond> s{{1, 9}, {2, 3}, {3, 6}};
    for (const auto& p : s) std::cout << p.first << ':' << p.second << ' ';
    std::cout << '\n';
    return 0;
}

المقارنات الشفافة

يتيح استخدام std::less<>، مع الأقواس الزاوية الفارغة، البحث غير المتجانس في C++14، مع تجنب تحويلات المفاتيح المؤقتة.

#include <iostream>
#include <set>
#include <functional>

int main() {
    std::set<int, std::less<>> s{1, 2, 3};
    std::cout << (s.find(2) != s.end() ? "found" : "no") << '\n';
    return 0;
}

تحقق سريع

اختبر مدى فهمك لكيفية تحديد المقارنات للتساوي.

مراجعة

تعلمت أن المقارنات المخصصة:

  • تغير الترتيب عبر معامل قالب المقارن الخاص بالحاوية
  • يمكن أن تكون std::greater، أو struct كائناً دالياً، أو lambda عبر decltype
  • تحدد التساوي بالتكافؤ، لذلك احرص دائماً على إضافة كاسر للتعادل لتجنب فقدان العناصر المميزة

الدورة التالية: البحث السريع القائم على التجزئة باستخدام std::unordered_map.

الأسئلة الشائعة

هل درس «المقارنات المخصّصة» مجاني؟

نعم — نص درس «المقارنات المخصّصة» كامل متاح مجاناً هنا على الويب. لتمرينه بشكل تفاعلي (محرر أكواد مدمج ومدرس ذكاء اصطناعي متاح 24/7) وفتح باقي دورة C++ Academy، انتقل إلى CoddyKit PRO. تتضمن دورة C++ Academy 4 دروس في المجموع.

ماذا ستتعلم في «المقارنات المخصّصة»؟

تحكّم في الترتيب تتمرن على C++ Academy مع أكواد عملية تشغلها مباشرة في المتصفح، ومدرس ذكاء اصطناعي متاح 24/7 يجيب على أسئلتك أثناء عملك.

هل أحتاج إلى خبرة سابقة لأبدأ C++ Academy؟

لا تُشترط خبرة سابقة. C++ Academy على CoddyKit منظم للمبتدئين حتى المتقدمين، لذا يمكنك البدء من هنا أو من البداية والتقدم بسرعتك الخاصة. هذا هو الدرس 4 من أصل 4.

كم من الوقت يستغرق درس «المقارنات المخصّصة»؟

معظم دروس CoddyKit تستغرق حوالي 5–10 دقائق. كل منها موجز وتفاعلي، لذا تحرز تقدماً مستمراً وتستأنف من حيث توقفت عبر الويب والتطبيق.

هل يمكنني كتابة وتشغيل أكواد في درس C++ Academy هذا؟

نعم. كل درس في C++ Academy يتضمن محرر أكواد مدمج، لذا تكتب وتشغل أكواداً حقيقية مباشرة في متصفحك وتحصل على تعليقات فورية من الذكاء الاصطناعي — بدون إعداد محلي.

جميع الدروس في هذه الدورة

  1. std::map
  2. std::set
  3. multimap وmultiset
  4. المقارنات المخصّصة
← العودة إلى C++ Academy