طَبِّقْهاتعلّم المبدأ، وطبّقه بيدكمقرر 101 · تركيب البيانات والخوارزميات
الدرس 9 · الوحدة 5: تحليل الأداء الزمني للخوارزميات

ترميز O الكبير

كلمة واحدة تصف كيف ستتصرف خوارزميتك حين تصبح البيانات مليونًا. ⏱ نحو 30 دقيقة.

بعد هذا الدرس ستستطيع أن:
  • تشرح الغرض من ترميز O الكبير.
  • تميّز التعقيدات الشائعة من O(1) إلى O(2ⁿ) وترتبها.
  • تبسّط التعبير بحذف الثوابت والحدود الصغرى.
  • تقدّر تعقيد مقطع كود من بنية حلقاته.

١لماذا ترميز O؟

لا نريد أن نقول «تستغرق 3 ثوانٍ»، فهذا يعتمد على الجهاز. نريد أن نصف كيف ينمو عدد العمليات حين يكبر حجم المدخل n. ترميز O الكبير Big O يعطي هذا الوصف في كلمة واحدة، ويركز على الحالة الأسوأ.

حجم المدخل n ←عدد العملياتO(1)O(log n)O(n)O(n log n)O(n²)O(2ⁿ)
كلما ارتفع المنحنى أسرع، صارت الخوارزمية أبطأ مع البيانات الكبيرة.

٢التعقيدات الشائعة

الترميزالاسممثالمضاعفة n تجعل العمل…
O(1)ثابتالوصول إلى a[5]، والبحث في dictكما هو
O(log n)لوغاريتميالبحث الثنائييزيد خطوة واحدة
O(n)خطيالبحث الخطي، ومجموع القائمةيتضاعف
O(n log n)شبه خطيالترتيب بالدمج، و sortedيتضاعف وأكثر قليلًا
O(n²)تربيعيمقارنة كل عنصر بكل عنصر، والترتيب الفقاعي×4
O(2ⁿ)أُسّيتجربة كل المجموعات الجزئيةيتربع! (غير عملي)
main.py
import mathprint(f"{'n':>8} {'log n':>6} {'n log n':>9} {'n²':>14}")for n in [10, 100, 1000, 10000, 100000]:    print(f"{n:>8} {round(math.log2(n)):>6} {round(n * math.log2(n)):>9} {n * n:>14}")
Shell×
>>> %Run main.py
n log n n log n n²
10 3 33 100
100 7 664 10000
1000 10 9966 1000000
10000 13 132877 100000000
100000 17 1660964 10000000000
>>>

٣قاعدتان للتبسيط

O يصف النمو مع البيانات الكبيرة جدًّا، لذلك نهمل ما لا يؤثر حين يكبر n:

القاعدةمثال
1. احذف الثوابت: الضرب في رقم ثابت لا يغيّر شكل النمو.3n + 5 ← O(n)، و n / 2 ← O(n)
2. أبقِ الحد الأكبر فقط: الحدود الأصغر تختفي مع n الكبير.n² + 100n + 7 ← O(n²)
main.py
# لماذا نهمل 100n أمام n²؟for n in [10, 1000, 100000]:    big = n * n    small = 100 * n    print(n, "| n²:", big, "| 100n:", small, "| نسبة 100n من المجموع:", round(small / (big + small) * 100, 2), "%")
Shell×
>>> %Run main.py
10 | n²: 100 | 100n: 1000 | نسبة 100n من المجموع: 90.91 %
1000 | n²: 1000000 | 100n: 100000 | نسبة 100n من المجموع: 9.09 %
100000 | n²: 10000000000 | 100n: 10000000 | نسبة 100n من المجموع: 0.1 %
>>>

٤اقرأ التعقيد من الكود

الكودالتعقيدالسبب
x = a[0] + a[-1]O(1)عدد ثابت من العمليات مهما كان طول a
for x in a: total += xO(n)مرور واحد على n عنصر
for x in a: for y in a: …O(n²)n دورة داخل n دورة
for x in a: … ثم for y in a: …O(n)حلقتان متتاليتان: 2n ← O(n)
while n > 1: n = n // 2O(log n)n ينقسم نصفين في كل دورة
sorted(a)O(n log n)خوارزمية Timsort

٥O و Ω و Θ

للاطلاع: يستخدم المختصون ثلاثة رموز. O حد أعلى (لن تكون أسوأ من هذا)، و Ω أوميغا حد أدنى (لن تكون أفضل من هذا)، و Θ ثيتا حين يتطابقان. في الحياة العملية حين يقول المبرمج «O(n)» يقصد غالبًا الحالة الأسوأ كما في هذا المقرر.

توقّع وتحقّق

بسّط: 5n² + 3n + 20

الحد الأكبر بلا ثوابت.

البحث الثنائي:

يقسم نصفين.

حلقتان متداخلتان على القائمة نفسها:

n × n.

الوصول إلى a[1000]:

مباشر.

الخلاصة

تحدٍّ برمجي: صنّف الدوال

متوسط

لكل دالة من الثلاث: عدّ عملياتها بعدّاد لـ n = 8 و n = 16، واطبع النسبة بين العددين، ثم اطبع تعقيدها.

المطلوب:
  • f1: حلقة واحدة على n. و f2: حلقتان متداخلتان. و f3: نقسم n على 2 حتى يصبح 1.
  • كل دالة تُرجع عدد مرات تنفيذ جسم الحلقة الداخلية.
  • اطبع لكل دالة: الاسم، والعددين، والنسبة، والتعقيد، مثل: f1 8 16 2.0 O(n)

ابدأ من هذا الكود، واضغط ▶ شغّل هنا لتكتب حلّك وتجرّبه مباشرة:

main.py
def f1(n):    c = 0    for i in range(n):        c += 1    return c # اكتب f2 و f3 ثم اطبع
المطلوب×
f1 8 16 2.0 O(n)
f2 64 256 4.0 O(n²)
f3 3 4 1.3333333333333333 O(log n)
💡 تلميح 1
f3: while n > 1: n = n // 2
💡 تلميح 2
النسبة: f(16) / f(8). لاحظ: 2 ثم 4 ثم 1.33

حاول بنفسك أولًا؛ للمسألة أكثر من حلّ صحيح.

main.py
def f1(n):    c = 0    for i in range(n):        c += 1    return c def f2(n):    c = 0    for i in range(n):        for j in range(n):            c += 1    return c def f3(n):    c = 0    while n > 1:        n = n // 2        c += 1    return c for name, f, big in [("f1", f1, "O(n)"), ("f2", f2, "O(n²)"), ("f3", f3, "O(log n)")]:    print(name, f(8), f(16), f(16) / f(8), big)
انتقل إلى تقييم الدرساختيار من متعدد، وصح وخطأ، وأكمل الفراغ، وتتبّع الناتج.ابدأ التقييم ←

📝 معلم؟ أرسل ملاحظة للمؤلف عن هذا الدرس