0Pricing
C++ Academy · درس

اعتبارات الأداء

تعرّف على الحاويات ومعامل التحميل

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

كيفية تخزين جداول التجزئة للبيانات

تحتوي الحاوية غير المرتبة على مصفوفة من الحاويات. وتحدد تجزئة المفتاح الحاوية التي ينتمي إليها؛ وتشكل المفاتيح المتعددة في حاوية واحدة سلسلة يجري البحث فيها خطياً.

#include <iostream>
#include <unordered_map>

int main() {
    std::unordered_map<int, int> m{{1, 1}, {2, 2}, {3, 3}};
    std::cout << "bucket count: " << m.bucket_count() << '\n';
    return 0;
}

أي حاوية؟

تخبرك bucket(key) بفهرس الحاوية التي يُرسم إليها المفتاح حالياً.

#include <iostream>
#include <unordered_map>

int main() {
    std::unordered_map<int, int> m{{10, 1}, {20, 2}, {30, 3}};
    std::cout << "key 20 in bucket " << m.bucket(20) << '\n';
    return 0;
}

عامل التحميل

إن عامل التحميل هو size / bucket_count. ويؤدي التحميل الأعلى إلى سلاسل أطول وعمليات بحث أبطأ.

#include <iostream>
#include <unordered_map>

int main() {
    std::unordered_map<int, int> m{{1, 1}, {2, 2}};
    std::cout << "load factor: " << m.load_factor() << '\n';
    return 0;
}

الحد الأقصى لعامل التحميل

تمثل max_load_factor() الحد الفاصل. وعندما يتجاوزه عامل التحميل، يعيد الجدول التجزئة إلى عدد أكبر من الحاويات.

#include <iostream>
#include <unordered_map>

int main() {
    std::unordered_map<int, int> m;
    std::cout << "default max load: " << m.max_load_factor() << '\n';
    return 0;
}

إعادة التجزئة

تعيد إعادة التجزئة بناء الجدول باستخدام عدد أكبر من الحاويات، وهي عملية مكلفة. وتحدث تلقائياً عند تجاوز عامل التحميل.

#include <iostream>
#include <unordered_map>

int main() {
    std::unordered_map<int, int> m;
    std::size_t before = m.bucket_count();
    for (int i = 0; i < 100; ++i) m[i] = i;
    std::cout << before << " -> " << m.bucket_count() << " buckets\n";
    return 0;
}

استخدام reserve لتجنب إعادة التجزئة

إذا كنت تعرف الحجم مسبقاً، فاستدعِ reserve(n) لتخصيص الحاويات مسبقاً وتجنب إعادة التجزئة المتكررة.

#include <iostream>
#include <unordered_map>

int main() {
    std::unordered_map<int, int> m;
    m.reserve(1000);
    std::cout << "buckets reserved: " << (m.bucket_count() >= 1000 ? "yes" : "no") << '\n';
    return 0;
}

إعادة التجزئة مباشرة

تضبط rehash(n) عدد الحاويات على قيمة لا تقل عن n. استخدم reserve لأعداد العناصر، وrehash لأعداد الحاويات.

#include <iostream>
#include <unordered_map>

int main() {
    std::unordered_map<int, int> m;
    m.rehash(64);
    std::cout << "buckets >= 64: " << (m.bucket_count() >= 64 ? "yes" : "no") << '\n';
    return 0;
}

فحص أحجام الحاويات

تكشف bucket_size(i) عدد العناصر التي تشترك في الحاوية i، وهو أمر مفيد لتشخيص التصادمات.

#include <iostream>
#include <unordered_map>

int main() {
    std::unordered_map<int, int> m;
    for (int i = 0; i < 10; ++i) m[i] = i;
    std::cout << "bucket 0 holds " << m.bucket_size(0) << " elements\n";
    return 0;
}

أسوأ حالة هي O(n)

عند استخدام دالة تجزئة سيئة تؤدي إلى تصادمات كثيرة، تتسلسل جميع المفاتيح في حاوية واحدة وتتدهور العمليات إلى وقت خطي. وتحافظ دالة التجزئة الجيدة على الأداء O(1).

#include <iostream>
#include <unordered_map>

int main() {
    std::unordered_map<int, int> m;
    for (int i = 0; i < 5; ++i) m[i] = i * i;
    std::cout << "avg lookups stay fast with good hashing\n";
    std::cout << "load: " << m.load_factor() << '\n';
    return 0;
}

خفض الحد الأقصى لعامل التحميل

يستبدل ضبط max_load_factor على قيمة أقل الذاكرة بالسرعة: تصادمات أقل، لكن عدد حاويات أكبر.

#include <iostream>
#include <unordered_map>

int main() {
    std::unordered_map<int, int> m;
    m.max_load_factor(0.5f);
    std::cout << "new max load: " << m.max_load_factor() << '\n';
    return 0;
}

إبطال المكررات

تؤدي إعادة التجزئة إلى إبطال المكررات، لكنها تبقي المراجع والمؤشرات إلى العناصر صالحة. خطط للحلقات وفقاً لذلك.

#include <iostream>
#include <unordered_map>

int main() {
    std::unordered_map<int, int> m{{1, 100}};
    int& ref = m[1];
    m.reserve(500);
    std::cout << "reference still valid: " << ref << '\n';
    return 0;
}

اختبار سريع

اختبروا فهمكم لأداء جدول التجزئة.

خلاصة

لقد تعلمتم آليات عمل جدول التجزئة الداخلية:

  • تُطابِق المفاتيح الحاويات؛ وتُشكّل التصادمات سلاسل
  • معامل التحميل = size / bucket_count؛ ويؤدي تجاوز max_load_factor إلى تفعيل إعادة التجزئة
  • استخدموا reserve لتجنب إعادة التجزئة؛ إذ تؤدي إعادة التجزئة إلى إبطال صلاحية المكررات، لكنها لا تُبطل صلاحية المراجع

الدورة التالية: قراءة الملفات وكتابتها باستخدام fstream.

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

هل درس «اعتبارات الأداء» مجاني؟

نعم — نص درس «اعتبارات الأداء» كامل متاح مجاناً هنا على الويب. لتمرينه بشكل تفاعلي (محرر أكواد مدمج ومدرس ذكاء اصطناعي متاح 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::unordered_map
  2. unordered_set
  3. دوال التجزئة المخصّصة
  4. اعتبارات الأداء
← العودة إلى C++ Academy