المستوى: مبتدئ. لو لسه بتتعلم البرمجة وبتسمع الناس بتقول "الكود ده O(n)" أو "ده O(n²)" ومش فاهم يعني إيه ولا ليه ده مهم، المقال ده مكتوب علشانك بالظبط.
Big O Notation للمبتدئ: ليه كودك بطيء وانت مش حاسس
الكود اللي كتبته الصبح اشتغل تمام على 100 صف من بيانات الـ test. على بيانات الإنتاج بـ 100 ألف صف نفس الكود بياخد دقيقة وربع. الفرق ده مش غلطة في السيرفر ولا مشكلة شبكة. اسمه Time Complexity، وفهمه بيوفّر عليك ساعات تشخيص لاحقًا.
المشكلة باختصار
أي دالة محلية بـ 50 عنصر بتشتغل في ميكروثواني، حتى لو مكتوبة بأسوأ طريقة ممكنة. المشكلة بتظهر في نقطتين: لمّا البيانات تكبر، ولمّا الـ traffic يكبر. الفرق بين دالة O(n) ودالة O(n²) ممكن يكون الفرق بين endpoint بيرد في 40 مللي ثانية و endpoint بياخد 4 دقايق على نفس الجدول.
مثال حسي قبل التعريف العلمي
تخيّل عندك قاموس عربي ورقي فيه 10,000 كلمة. عايز تلاقي كلمة "نظام". في 3 طرق ممكنة:
- الطريقة الأولى — تقرأ كل كلمة: تفتح صفحة 1 وتقرا، بعدين 2، وهكذا. لو الكلمة في الآخر، قريت 10,000 كلمة. الزمن بيكبر بنفس معدل عدد الكلمات. ده اللي اسمه
O(n). - الطريقة الثانية — تفتح في النص: تفتح في النص، تشوف "ن" قبل ولا بعد، تقفل النص اللي مش فيه وتعيد على النص اللي فيه. كل خطوة بتنصّف الباقي. لـ 10,000 كلمة هتاخد 14 خطوة فقط. ده
O(log n). - الطريقة الثالثة — index على كل حرف: القاموس فيه فاصل على كل حرف. بتفتح على "ن" دايركت وبتلاقي كلمتك. مهما زاد حجم القاموس، الزمن نفسه. ده
O(1).
المثال ده بيوضّح إن نفس المهمة "ابحث عن كلمة" ممكن تتعمل بـ 3 سرعات مختلفة جذريًا، حسب البنية اللي اخترتها. الكود بالظبط زي القاموس.
التعريف العلمي بدقة
Big O Notation هو طريقة رياضية لوصف كيف ينمو زمن أو ذاكرة الخوارزمية لمّا حجم المدخلات يكبر. الـ n بيمثّل عدد العناصر. صياغة O(f(n)) بتقول إن الزمن في أسوأ حالة بيكبر بمعدل f(n) على الأكثر.
التعريف الرسمي اللي قدّمه Donald Knuth في ورقته البحثية على ACM SIGACT News سنة 1976: الدالة g(n) هي O(f(n)) لو في ثوابت موجبة c و n0 بحيث يكون g(n) ≤ c · f(n) لكل n ≥ n0. التعريف ده هو اللي بنى عليه الكتاب الأشهر في علم الحوسبة "Introduction to Algorithms" (CLRS).
أربع تعقيدات لازم تعرفها
O(1) — الزمن الثابت
الكود بياخد نفس الزمن مهما كان حجم البيانات. الوصول لعنصر في array بـ index، الإضافة لـ HashMap، الـ push على stack — كلهم O(1).